198 lines
6.9 KiB
C++
198 lines
6.9 KiB
C++
/*
|
|
* 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 <functional>
|
|
#include <iostream>
|
|
#include <unordered_map>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "vhal_v2_0/SubscriptionManager.h"
|
|
|
|
#include "VehicleHalTestUtils.h"
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace automotive {
|
|
namespace vehicle {
|
|
namespace V2_0 {
|
|
|
|
namespace {
|
|
|
|
using namespace std::placeholders;
|
|
|
|
class SubscriptionManagerTest : public ::testing::Test {
|
|
public:
|
|
SubscriptionManagerTest() : manager(([this](int x) { onPropertyUnsubscribed(x); })) {}
|
|
|
|
SubscriptionManager manager;
|
|
static constexpr int32_t PROP1 = toInt(VehicleProperty::HVAC_FAN_SPEED);
|
|
static constexpr int32_t PROP2 = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
|
|
|
|
sp<IVehicleCallback> cb1 = new MockedVehicleCallback();
|
|
sp<IVehicleCallback> cb2 = new MockedVehicleCallback();
|
|
sp<IVehicleCallback> cb3 = new MockedVehicleCallback();
|
|
|
|
void SetUp() override {
|
|
lastUnsubscribedProperty = -1;
|
|
}
|
|
|
|
hidl_vec<SubscribeOptions> subscrToProp1 = {
|
|
SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
|
|
};
|
|
|
|
hidl_vec<SubscribeOptions> subscrToProp2 = {
|
|
SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
|
|
};
|
|
|
|
hidl_vec<SubscribeOptions> subscrToProp1and2 = {
|
|
SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR},
|
|
SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::EVENTS_FROM_CAR},
|
|
};
|
|
|
|
static std::list<sp<IVehicleCallback>> extractCallbacks(
|
|
const std::list<sp<HalClient>>& clients) {
|
|
std::list<sp<IVehicleCallback>> callbacks;
|
|
for (const auto& c : clients) {
|
|
callbacks.push_back(c->getCallback());
|
|
}
|
|
return callbacks;
|
|
}
|
|
|
|
std::list<sp<HalClient>> clientsToProp1() {
|
|
return manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
|
|
}
|
|
|
|
std::list<sp<HalClient>> clientsToProp2() {
|
|
return manager.getSubscribedClients(PROP2, SubscribeFlags::EVENTS_FROM_CAR);
|
|
}
|
|
|
|
void onPropertyUnsubscribed(int propertyId) {
|
|
// Called when there are no clients who subscribed to particular property. This can happen
|
|
// because of explict unsubscribe call or when client (IVehicleCallback) was disconnected.
|
|
lastUnsubscribedProperty = propertyId;
|
|
}
|
|
|
|
void assertOnPropertyUnsubscribedNotCalled() {
|
|
ASSERT_EQ(-1, lastUnsubscribedProperty);
|
|
}
|
|
|
|
void assertLastUnsubscribedProperty(int expectedPropertyId) {
|
|
ASSERT_EQ(expectedPropertyId, lastUnsubscribedProperty);
|
|
lastUnsubscribedProperty = -1;
|
|
}
|
|
|
|
private:
|
|
int lastUnsubscribedProperty;
|
|
};
|
|
|
|
|
|
TEST_F(SubscriptionManagerTest, multipleClients) {
|
|
std::list<SubscribeOptions> updatedOptions;
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(2, cb2, subscrToProp1, &updatedOptions));
|
|
|
|
auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
|
|
|
|
ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
|
|
}
|
|
|
|
TEST_F(SubscriptionManagerTest, negativeCases) {
|
|
std::list<SubscribeOptions> updatedOptions;
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
|
|
|
|
// Wrong prop
|
|
auto clients = manager.getSubscribedClients(toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
|
|
SubscribeFlags::EVENTS_FROM_CAR);
|
|
ASSERT_TRUE(clients.empty());
|
|
|
|
// Wrong flag
|
|
clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_ANDROID);
|
|
ASSERT_TRUE(clients.empty());
|
|
}
|
|
|
|
TEST_F(SubscriptionManagerTest, mulipleSubscriptions) {
|
|
std::list<SubscribeOptions> updatedOptions;
|
|
ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, subscrToProp1,
|
|
&updatedOptions));
|
|
|
|
auto clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
|
|
ASSERT_EQ((size_t) 1, clients.size());
|
|
ASSERT_EQ(cb1, clients.front()->getCallback());
|
|
|
|
// Same property, but different zone, to make sure we didn't unsubscribe
|
|
// from previous zone.
|
|
ASSERT_EQ(
|
|
StatusCode::OK,
|
|
manager.addOrUpdateSubscription(
|
|
1, cb1, {SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::EVENTS_FROM_CAR}},
|
|
&updatedOptions));
|
|
|
|
clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
|
|
ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
|
|
|
|
clients = manager.getSubscribedClients(PROP1, SubscribeFlags::EVENTS_FROM_CAR);
|
|
ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
|
|
}
|
|
|
|
TEST_F(SubscriptionManagerTest, unsubscribe) {
|
|
std::list<SubscribeOptions> updatedOptions;
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(2, cb2, subscrToProp2, &updatedOptions));
|
|
ASSERT_EQ(StatusCode::OK,
|
|
manager.addOrUpdateSubscription(3, cb3, subscrToProp1and2, &updatedOptions));
|
|
|
|
ASSERT_ALL_EXISTS({ cb1, cb3 }, extractCallbacks(clientsToProp1()));
|
|
ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
|
|
|
|
manager.unsubscribe(1, PROP1);
|
|
assertOnPropertyUnsubscribedNotCalled();
|
|
ASSERT_ALL_EXISTS({cb3}, extractCallbacks(clientsToProp1()));
|
|
|
|
// Make sure nothing changed in PROP2 so far.
|
|
ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
|
|
|
|
// No one subscribed to PROP1, subscription for PROP2 is not affected.
|
|
manager.unsubscribe(3, PROP1);
|
|
assertLastUnsubscribedProperty(PROP1);
|
|
ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
|
|
|
|
manager.unsubscribe(3, PROP2);
|
|
assertOnPropertyUnsubscribedNotCalled();
|
|
ASSERT_ALL_EXISTS({cb2}, extractCallbacks(clientsToProp2()));
|
|
|
|
// The last client unsubscribed from this property.
|
|
manager.unsubscribe(2, PROP2);
|
|
assertLastUnsubscribedProperty(PROP2);
|
|
|
|
// No one subscribed anymore
|
|
manager.unsubscribe(1, PROP1);
|
|
assertLastUnsubscribedProperty(PROP1);
|
|
}
|
|
|
|
} // namespace anonymous
|
|
|
|
} // namespace V2_0
|
|
} // namespace vehicle
|
|
} // namespace automotive
|
|
} // namespace hardware
|
|
} // namespace android
|