1 /*
2  * Copyright (C) 2016 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 <unistd.h>
18 
19 #include <gtest/gtest.h>
20 #include <binder/IServiceManager.h>
21 #include <binder/ProcessState.h>
22 #include <utils/threads.h>
23 #include <utils/KeyedVector.h>
24 #include <utils/String8.h>
25 #include <utils/SystemClock.h>
26 #include <VehiclePropertyAccessControlForTesting.h>
27 
28 namespace android {
29 
30 class VehiclePropertyAccessControlTest : public testing::Test {
31 public:
VehiclePropertyAccessControlTest()32     VehiclePropertyAccessControlTest() {}
~VehiclePropertyAccessControlTest()33     ~VehiclePropertyAccessControlTest() {}
34 
35 public:
36     static std::string xmlData;
37     static std::string xmlData2;
38     static const int32_t prop1;
39     static const int32_t prop2;
40     static const int32_t prop3;
41     static const int32_t uid1;
42     static const int32_t uid2;
43     static const int32_t uid3;
44 
45 protected:
SetUp()46     void SetUp() {}
47 
48 protected:
49     xmlDoc* doc;
50     VehiclePropertyAccessControlForTesting mVehiclePropertyAccessControl;
51 };
52 
53 std::string VehiclePropertyAccessControlTest::xmlData =
54                             "<ALLOW>"
55                             "<PROPERTY name=\"PROP1\" value=\"0xA\">"
56                             "<UID name=\"UID1\" access=\"r\" value=\"1000\"/>"
57                             "</PROPERTY>"
58                             "<PROPERTY name=\"PROP2\" value=\"0xB\">"
59                             "<UID name=\"UID2\" access=\"w\" value=\"2000\"/>"
60                             "</PROPERTY>"
61                             "<PROPERTY name=\"PROP3\" value=\"0xC\">"
62                             "<UID name=\"UID3\" access=\"rw\" value=\"3000\"/>"
63                             "</PROPERTY>"
64                             "</ALLOW>";
65 
66 const int32_t VehiclePropertyAccessControlTest::prop1 = 0xa;
67 const int32_t VehiclePropertyAccessControlTest::prop2 = 0xb;
68 const int32_t VehiclePropertyAccessControlTest::prop3 = 0xc;
69 const int32_t VehiclePropertyAccessControlTest::uid1 = 1000;
70 const int32_t VehiclePropertyAccessControlTest::uid2 = 2000;
71 const int32_t VehiclePropertyAccessControlTest::uid3 = 3000;
72 
TEST_F(VehiclePropertyAccessControlTest,isHexNotation)73 TEST_F(VehiclePropertyAccessControlTest, isHexNotation) {
74     static const std::string shouldPass[] =
75         {"0x01234567",
76          "0x01abcdef",
77          "0x01ABCDEF",
78          "0x0"};
79 
80     static const std::string shouldFail[] =
81         {"0",
82          "0x",
83          "01234567",
84          "ABCDEF01",
85          "0xabi"};
86 
87     for(auto& h : shouldPass) {
88         ASSERT_TRUE(mVehiclePropertyAccessControl.isHexNotation(h));
89     }
90 
91     for(auto& h : shouldFail) {
92         ASSERT_FALSE(mVehiclePropertyAccessControl.isHexNotation(h));
93     }
94 }
95 
TEST_F(VehiclePropertyAccessControlTest,accessToInt)96 TEST_F(VehiclePropertyAccessControlTest, accessToInt) {
97     static const char* property = "property";
98     static const char* uid = "uid";
99     struct ShouldPassType {std::string str; int32_t value;};
100     static const struct ShouldPassType shouldPass[] = {
101             {"r", VEHICLE_PROP_ACCESS_READ},
102             {"w", VEHICLE_PROP_ACCESS_WRITE},
103             {"rw", VEHICLE_PROP_ACCESS_READ_WRITE},
104             {"wr", VEHICLE_PROP_ACCESS_READ_WRITE}
105     };
106     static const char* shouldFail[] = {"rr", "ww", "rww", "rwr", "", "k"};
107     int32_t value;
108 
109     for(auto& h : shouldPass) {
110         ASSERT_TRUE(mVehiclePropertyAccessControl.accessToInt(&value,
111             (const xmlChar*)property, (const xmlChar*)uid,
112             (const xmlChar*)h.str.c_str()));
113         ASSERT_EQ(h.value, value);
114     }
115 
116     for(auto& h : shouldFail) {
117         ASSERT_FALSE(mVehiclePropertyAccessControl.accessToInt(&value,
118             (const xmlChar*)property, (const xmlChar*)uid, (const xmlChar*)h));
119     }
120 }
121 
TEST_F(VehiclePropertyAccessControlTest,updateOrCreate)122 TEST_F(VehiclePropertyAccessControlTest, updateOrCreate) {
123     std::map<int32_t, int32_t> *accessMap;
124 
125     // Empty the map
126     mVehiclePropertyAccessControl.emptyAccessControlMap();
127 
128     // Make sure the property does not exist
129     ASSERT_FALSE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
130                                                                    &accessMap));
131 
132     // Create the property and give uid read access
133     ASSERT_FALSE(mVehiclePropertyAccessControl.updateOrCreate(uid1, prop1,
134                                                  VEHICLE_PROP_ACCESS_READ));
135 
136     // Make sure the property was created
137     ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
138                                                                    &accessMap));
139 
140     // Make sure uid has read access to the property
141     ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
142 
143     // Give uid2 read/write access to the property
144     ASSERT_FALSE(mVehiclePropertyAccessControl.updateOrCreate(uid2, prop1,
145                                                 VEHICLE_PROP_ACCESS_READ_WRITE));
146 
147     // Get the accessMap
148     ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
149                                                                    &accessMap));
150     // Make sure uid2 has read/write access to the property
151     ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_READ_WRITE);
152 
153     // Make sure uid still has read access to the property
154     ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
155 
156     // Change uid access to write for property
157     ASSERT_TRUE(mVehiclePropertyAccessControl.updateOrCreate(uid1, prop1,
158                                                      VEHICLE_PROP_ACCESS_WRITE));
159 
160     // Get the accessMap
161     ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
162                                                                    &accessMap));
163 
164     // Make sure uid has write access to property
165     ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_WRITE);
166 
167     // Make sure uid2 has read write access to property
168     ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_READ_WRITE);
169 }
170 
TEST_F(VehiclePropertyAccessControlTest,populate)171 TEST_F(VehiclePropertyAccessControlTest, populate) {
172     xmlNode* root_element;
173     std::map<int32_t, int32_t> *accessMap;
174 
175     // Empty the map
176     mVehiclePropertyAccessControl.emptyAccessControlMap();
177 
178     doc = xmlReadMemory(xmlData.c_str(), xmlData.length(), NULL, NULL, 0);
179     ASSERT_TRUE(doc != NULL);
180     root_element = xmlDocGetRootElement(doc);
181     ASSERT_TRUE(root_element != NULL);
182 
183     bool result = mVehiclePropertyAccessControl.populate(root_element->children);
184 
185     ASSERT_TRUE(result);
186 
187     // Get the accessMap
188     ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
189                                                                   &accessMap));
190 
191     // Make sure uid still has read access to the property
192     ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
193 
194     // Get the accessMap
195     ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop2,
196                                                                   &accessMap));
197 
198     // Make sure uid still has write access to the property
199     ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_WRITE);
200 
201     ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop1, uid1, 0));
202     ASSERT_FALSE(mVehiclePropertyAccessControl.testAccess(prop1, uid1, 1));
203     ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop2, uid2, 1));
204     ASSERT_FALSE(mVehiclePropertyAccessControl.testAccess(prop2, uid2, 0));
205     ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop3, uid3, 1));
206     ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop3, uid3, 0));
207 
208     static const std::string dump_msg =
209             "UID 1000: property 0x0000000a, access read\n"
210             "UID 2000: property 0x0000000b, access write\n"
211             "UID 3000: property 0x0000000c, access read/write\n";
212 
213     String8 msg;
214     mVehiclePropertyAccessControl.dump(msg);
215 
216     ASSERT_EQ(dump_msg.compare(msg.string()), 0);
217 
218 }
219 
TEST_F(VehiclePropertyAccessControlTest,init)220 TEST_F(VehiclePropertyAccessControlTest, init) {
221     xmlFreeDoc(doc);
222     xmlCleanupParser();
223     // Empty the map
224     mVehiclePropertyAccessControl.emptyAccessControlMap();
225     ASSERT_TRUE(mVehiclePropertyAccessControl.init());
226 }
227 }; // namespace android
228