/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <gtest/gtest.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <VehiclePropertyAccessControlForTesting.h>
namespace android {
class VehiclePropertyAccessControlTest : public testing::Test {
public:
VehiclePropertyAccessControlTest() {}
~VehiclePropertyAccessControlTest() {}
public:
static std::string xmlData;
static std::string xmlData2;
static const int32_t prop1;
static const int32_t prop2;
static const int32_t prop3;
static const int32_t uid1;
static const int32_t uid2;
static const int32_t uid3;
protected:
void SetUp() {}
protected:
xmlDoc* doc;
VehiclePropertyAccessControlForTesting mVehiclePropertyAccessControl;
};
std::string VehiclePropertyAccessControlTest::xmlData =
"<ALLOW>"
"<PROPERTY name=\"PROP1\" value=\"0xA\">"
"<UID name=\"UID1\" access=\"r\" value=\"1000\"/>"
"</PROPERTY>"
"<PROPERTY name=\"PROP2\" value=\"0xB\">"
"<UID name=\"UID2\" access=\"w\" value=\"2000\"/>"
"</PROPERTY>"
"<PROPERTY name=\"PROP3\" value=\"0xC\">"
"<UID name=\"UID3\" access=\"rw\" value=\"3000\"/>"
"</PROPERTY>"
"</ALLOW>";
const int32_t VehiclePropertyAccessControlTest::prop1 = 0xa;
const int32_t VehiclePropertyAccessControlTest::prop2 = 0xb;
const int32_t VehiclePropertyAccessControlTest::prop3 = 0xc;
const int32_t VehiclePropertyAccessControlTest::uid1 = 1000;
const int32_t VehiclePropertyAccessControlTest::uid2 = 2000;
const int32_t VehiclePropertyAccessControlTest::uid3 = 3000;
TEST_F(VehiclePropertyAccessControlTest, isHexNotation) {
static const std::string shouldPass[] =
{"0x01234567",
"0x01abcdef",
"0x01ABCDEF",
"0x0"};
static const std::string shouldFail[] =
{"0",
"0x",
"01234567",
"ABCDEF01",
"0xabi"};
for(auto& h : shouldPass) {
ASSERT_TRUE(mVehiclePropertyAccessControl.isHexNotation(h));
}
for(auto& h : shouldFail) {
ASSERT_FALSE(mVehiclePropertyAccessControl.isHexNotation(h));
}
}
TEST_F(VehiclePropertyAccessControlTest, accessToInt) {
static const char* property = "property";
static const char* uid = "uid";
struct ShouldPassType {std::string str; int32_t value;};
static const struct ShouldPassType shouldPass[] = {
{"r", VEHICLE_PROP_ACCESS_READ},
{"w", VEHICLE_PROP_ACCESS_WRITE},
{"rw", VEHICLE_PROP_ACCESS_READ_WRITE},
{"wr", VEHICLE_PROP_ACCESS_READ_WRITE}
};
static const char* shouldFail[] = {"rr", "ww", "rww", "rwr", "", "k"};
int32_t value;
for(auto& h : shouldPass) {
ASSERT_TRUE(mVehiclePropertyAccessControl.accessToInt(&value,
(const xmlChar*)property, (const xmlChar*)uid,
(const xmlChar*)h.str.c_str()));
ASSERT_EQ(h.value, value);
}
for(auto& h : shouldFail) {
ASSERT_FALSE(mVehiclePropertyAccessControl.accessToInt(&value,
(const xmlChar*)property, (const xmlChar*)uid, (const xmlChar*)h));
}
}
TEST_F(VehiclePropertyAccessControlTest, updateOrCreate) {
std::map<int32_t, int32_t> *accessMap;
// Empty the map
mVehiclePropertyAccessControl.emptyAccessControlMap();
// Make sure the property does not exist
ASSERT_FALSE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
&accessMap));
// Create the property and give uid read access
ASSERT_FALSE(mVehiclePropertyAccessControl.updateOrCreate(uid1, prop1,
VEHICLE_PROP_ACCESS_READ));
// Make sure the property was created
ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
&accessMap));
// Make sure uid has read access to the property
ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
// Give uid2 read/write access to the property
ASSERT_FALSE(mVehiclePropertyAccessControl.updateOrCreate(uid2, prop1,
VEHICLE_PROP_ACCESS_READ_WRITE));
// Get the accessMap
ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
&accessMap));
// Make sure uid2 has read/write access to the property
ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_READ_WRITE);
// Make sure uid still has read access to the property
ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
// Change uid access to write for property
ASSERT_TRUE(mVehiclePropertyAccessControl.updateOrCreate(uid1, prop1,
VEHICLE_PROP_ACCESS_WRITE));
// Get the accessMap
ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
&accessMap));
// Make sure uid has write access to property
ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_WRITE);
// Make sure uid2 has read write access to property
ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_READ_WRITE);
}
TEST_F(VehiclePropertyAccessControlTest, populate) {
xmlNode* root_element;
std::map<int32_t, int32_t> *accessMap;
// Empty the map
mVehiclePropertyAccessControl.emptyAccessControlMap();
doc = xmlReadMemory(xmlData.c_str(), xmlData.length(), NULL, NULL, 0);
ASSERT_TRUE(doc != NULL);
root_element = xmlDocGetRootElement(doc);
ASSERT_TRUE(root_element != NULL);
bool result = mVehiclePropertyAccessControl.populate(root_element->children);
ASSERT_TRUE(result);
// Get the accessMap
ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop1,
&accessMap));
// Make sure uid still has read access to the property
ASSERT_EQ((*accessMap)[uid1], VEHICLE_PROP_ACCESS_READ);
// Get the accessMap
ASSERT_TRUE(mVehiclePropertyAccessControl.getAccessToProperty(prop2,
&accessMap));
// Make sure uid still has write access to the property
ASSERT_EQ((*accessMap)[uid2], VEHICLE_PROP_ACCESS_WRITE);
ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop1, uid1, 0));
ASSERT_FALSE(mVehiclePropertyAccessControl.testAccess(prop1, uid1, 1));
ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop2, uid2, 1));
ASSERT_FALSE(mVehiclePropertyAccessControl.testAccess(prop2, uid2, 0));
ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop3, uid3, 1));
ASSERT_TRUE(mVehiclePropertyAccessControl.testAccess(prop3, uid3, 0));
static const std::string dump_msg =
"UID 1000: property 0x0000000a, access read\n"
"UID 2000: property 0x0000000b, access write\n"
"UID 3000: property 0x0000000c, access read/write\n";
String8 msg;
mVehiclePropertyAccessControl.dump(msg);
ASSERT_EQ(dump_msg.compare(msg.string()), 0);
}
TEST_F(VehiclePropertyAccessControlTest, init) {
xmlFreeDoc(doc);
xmlCleanupParser();
// Empty the map
mVehiclePropertyAccessControl.emptyAccessControlMap();
ASSERT_TRUE(mVehiclePropertyAccessControl.init());
}
}; // namespace android