Home | History | Annotate | Download | only in tests
      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 <functional>
     18 #include <iostream>
     19 #include <unordered_map>
     20 
     21 #include <gtest/gtest.h>
     22 
     23 #include "vhal_v2_0/SubscriptionManager.h"
     24 
     25 #include "VehicleHalTestUtils.h"
     26 
     27 namespace android {
     28 namespace hardware {
     29 namespace automotive {
     30 namespace vehicle {
     31 namespace V2_0 {
     32 
     33 namespace {
     34 
     35 using namespace std::placeholders;
     36 
     37 class SubscriptionManagerTest : public ::testing::Test {
     38 public:
     39     SubscriptionManagerTest() : manager(([this](int x) { onPropertyUnsubscribed(x); })) {}
     40 
     41     SubscriptionManager manager;
     42     static constexpr int32_t PROP1 = toInt(VehicleProperty::HVAC_FAN_SPEED);
     43     static constexpr int32_t PROP2 = toInt(VehicleProperty::DISPLAY_BRIGHTNESS);
     44 
     45     sp<IVehicleCallback> cb1 = new MockedVehicleCallback();
     46     sp<IVehicleCallback> cb2 = new MockedVehicleCallback();
     47     sp<IVehicleCallback> cb3 = new MockedVehicleCallback();
     48 
     49     void SetUp() override {
     50         lastUnsubscribedProperty = -1;
     51     }
     52 
     53     hidl_vec<SubscribeOptions> subscrToProp1 = {
     54         SubscribeOptions {
     55             .propId = PROP1,
     56             .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
     57             .flags = SubscribeFlags::HAL_EVENT
     58         },
     59     };
     60 
     61     hidl_vec<SubscribeOptions> subscrToProp2 = {
     62         SubscribeOptions {
     63             .propId = PROP2,
     64             .flags = SubscribeFlags::HAL_EVENT
     65         },
     66     };
     67 
     68     hidl_vec<SubscribeOptions> subscrToProp1and2 = {
     69         SubscribeOptions {
     70             .propId = PROP1,
     71             .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
     72             .flags = SubscribeFlags::HAL_EVENT
     73         },
     74         SubscribeOptions {
     75             .propId = PROP2,
     76             .flags = SubscribeFlags::HAL_EVENT
     77         },
     78     };
     79 
     80     static std::list<sp<IVehicleCallback>> extractCallbacks(
     81             const std::list<sp<HalClient>>& clients) {
     82         std::list<sp<IVehicleCallback>> callbacks;
     83         for (auto c : clients) {
     84             callbacks.push_back(c->getCallback());
     85         }
     86         return callbacks;
     87     }
     88 
     89     std::list<sp<HalClient>> clientsToProp1() {
     90         return manager.getSubscribedClients(PROP1,
     91                                             toInt(VehicleAreaZone::ROW_1_LEFT),
     92                                             SubscribeFlags::DEFAULT);
     93     }
     94 
     95     std::list<sp<HalClient>> clientsToProp2() {
     96         return manager.getSubscribedClients(PROP2, 0,
     97                                             SubscribeFlags::DEFAULT);
     98     }
     99 
    100     void onPropertyUnsubscribed(int propertyId) {
    101         // Called when there are no clients who subscribed to particular property. This can happen
    102         // because of explict unsubscribe call or when client (IVehicleCallback) was disconnected.
    103         lastUnsubscribedProperty = propertyId;
    104     }
    105 
    106     void assertOnPropertyUnsubscribedNotCalled() {
    107         ASSERT_EQ(-1, lastUnsubscribedProperty);
    108     }
    109 
    110     void assertLastUnsubscribedProperty(int expectedPropertyId) {
    111         ASSERT_EQ(expectedPropertyId, lastUnsubscribedProperty);
    112         lastUnsubscribedProperty = -1;
    113     }
    114 
    115 private:
    116     int lastUnsubscribedProperty;
    117 };
    118 
    119 
    120 TEST_F(SubscriptionManagerTest, multipleClients) {
    121     std::list<SubscribeOptions> updatedOptions;
    122     ASSERT_EQ(StatusCode::OK,
    123               manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
    124     ASSERT_EQ(StatusCode::OK,
    125               manager.addOrUpdateSubscription(2, cb2, subscrToProp1, &updatedOptions));
    126 
    127     auto clients = manager.getSubscribedClients(
    128             PROP1,
    129             toInt(VehicleAreaZone::ROW_1_LEFT),
    130             SubscribeFlags::HAL_EVENT);
    131 
    132     ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
    133 }
    134 
    135 TEST_F(SubscriptionManagerTest, negativeCases) {
    136     std::list<SubscribeOptions> updatedOptions;
    137     ASSERT_EQ(StatusCode::OK,
    138               manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
    139 
    140     // Wrong zone
    141     auto clients = manager.getSubscribedClients(
    142             PROP1,
    143             toInt(VehicleAreaZone::ROW_2_LEFT),
    144             SubscribeFlags::HAL_EVENT);
    145     ASSERT_TRUE(clients.empty());
    146 
    147     // Wrong prop
    148     clients = manager.getSubscribedClients(
    149             toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
    150             toInt(VehicleAreaZone::ROW_1_LEFT),
    151             SubscribeFlags::HAL_EVENT);
    152     ASSERT_TRUE(clients.empty());
    153 
    154     // Wrong flag
    155     clients = manager.getSubscribedClients(
    156             PROP1,
    157             toInt(VehicleAreaZone::ROW_1_LEFT),
    158             SubscribeFlags::SET_CALL);
    159     ASSERT_TRUE(clients.empty());
    160 }
    161 
    162 TEST_F(SubscriptionManagerTest, mulipleSubscriptions) {
    163     std::list<SubscribeOptions> updatedOptions;
    164     ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, subscrToProp1,
    165                                                               &updatedOptions));
    166 
    167     auto clients = manager.getSubscribedClients(
    168             PROP1,
    169             toInt(VehicleAreaZone::ROW_1_LEFT),
    170             SubscribeFlags::DEFAULT);
    171     ASSERT_EQ((size_t) 1, clients.size());
    172     ASSERT_EQ(cb1, clients.front()->getCallback());
    173 
    174     // Same property, but different zone, to make sure we didn't unsubscribe
    175     // from previous zone.
    176     ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, {
    177         SubscribeOptions {
    178                 .propId = PROP1,
    179                 .vehicleAreas = toInt(VehicleAreaZone::ROW_2),
    180                 .flags = SubscribeFlags::DEFAULT
    181             }
    182         }, &updatedOptions));
    183 
    184     clients = manager.getSubscribedClients(PROP1,
    185                                            toInt(VehicleAreaZone::ROW_1_LEFT),
    186                                            SubscribeFlags::DEFAULT);
    187     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
    188 
    189     clients = manager.getSubscribedClients(PROP1,
    190                                            toInt(VehicleAreaZone::ROW_2),
    191                                            SubscribeFlags::DEFAULT);
    192     ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
    193 }
    194 
    195 TEST_F(SubscriptionManagerTest, unsubscribe) {
    196     std::list<SubscribeOptions> updatedOptions;
    197     ASSERT_EQ(StatusCode::OK,
    198               manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
    199     ASSERT_EQ(StatusCode::OK,
    200               manager.addOrUpdateSubscription(2, cb2, subscrToProp2, &updatedOptions));
    201     ASSERT_EQ(StatusCode::OK,
    202               manager.addOrUpdateSubscription(3, cb3, subscrToProp1and2, &updatedOptions));
    203 
    204     ASSERT_ALL_EXISTS({ cb1, cb3 }, extractCallbacks(clientsToProp1()));
    205     ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
    206 
    207     manager.unsubscribe(1, PROP1);
    208     assertOnPropertyUnsubscribedNotCalled();
    209     ASSERT_ALL_EXISTS({cb3}, extractCallbacks(clientsToProp1()));
    210 
    211     // Make sure nothing changed in PROP2 so far.
    212     ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
    213 
    214     // No one subscribed to PROP1, subscription for PROP2 is not affected.
    215     manager.unsubscribe(3, PROP1);
    216     assertLastUnsubscribedProperty(PROP1);
    217     ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
    218 
    219     manager.unsubscribe(3, PROP2);
    220     assertOnPropertyUnsubscribedNotCalled();
    221     ASSERT_ALL_EXISTS({cb2}, extractCallbacks(clientsToProp2()));
    222 
    223     // The last client unsubscribed from this property.
    224     manager.unsubscribe(2, PROP2);
    225     assertLastUnsubscribedProperty(PROP2);
    226 
    227     // No one subscribed anymore
    228     manager.unsubscribe(1, PROP1);
    229     assertLastUnsubscribedProperty(PROP1);
    230 }
    231 
    232 }  // namespace anonymous
    233 
    234 }  // namespace V2_0
    235 }  // namespace vehicle
    236 }  // namespace automotive
    237 }  // namespace hardware
    238 }  // namespace android
    239