Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2005a3e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Updates to VMS Utils to support HAL Client Publisher"

parents 00afcf7c cde1aa96
Loading
Loading
Loading
Loading
+62 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <memory>
#include <string>
#include <unordered_set>

#include <android/hardware/automotive/vehicle/2.0/types.h>

@@ -42,6 +43,20 @@ struct VmsLayer {
    int type;
    int subtype;
    int version;
    bool operator==(const VmsLayer& layer) const {
        return this->type == layer.type && this->subtype == layer.subtype &&
               this->version == layer.version;
    }

    // Class for hash function
    class VmsLayerHashFunction {
      public:
        // Hash of the variables is returned.
        size_t operator()(const VmsLayer& layer) const {
            return std::hash<int>()(layer.type) ^ std::hash<int>()(layer.type) ^
                   std::hash<int>()(layer.type);
        }
    };
};

struct VmsLayerAndPublisher {
@@ -66,6 +81,15 @@ struct VmsLayerOffering {
    std::vector<VmsLayer> dependencies;
};

// A VmsOffers refers to a list of layers that can be published by the publisher
// with the specified publisher ID.
struct VmsOffers {
    VmsOffers(int publisher_id, std::vector<VmsLayerOffering> offerings)
        : publisher_id(publisher_id), offerings(offerings) {}
    int publisher_id;
    std::vector<VmsLayerOffering> offerings;
};

// A VmsSubscriptionsState is delivered in response to a
// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
@@ -81,6 +105,9 @@ struct VmsAvailabilityState {
    std::vector<VmsAssociatedLayer> associated_layers;
};

// Creates an empty base VMS message with some pre-populated default fields.
std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size);

// Creates a VehiclePropValue containing a message of type
// VmsMessageType.SUBSCRIBE, specifying to the VMS service
// which layer to subscribe to.
@@ -106,8 +133,7 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
// offered and their dependencies, if any.
std::unique_ptr<VehiclePropValue> createOfferingMessage(
    const std::vector<VmsLayerOffering>& offering);
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers);

// Creates a VehiclePropValue containing a message of type
// VmsMessageType.AVAILABILITY_REQUEST.
@@ -143,8 +169,40 @@ VmsMessageType parseMessageType(const VehiclePropValue& value);
// function to ParseFromString.
std::string parseData(const VehiclePropValue& value);

// TODO(aditin): Need to implement additional parsing functions per message
// type.
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
// Returns a nullptr if the input is empty.
std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
        const std::string& vms_provider_description);

// Returns the publisher ID by parsing the VehiclePropValue containing the ID.
// Returns null if the message is invalid.
int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response);

// Returns true if the new sequence number is greater than the last seen
// sequence number.
bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
                           const int last_seen_sequence_number);

// Returns sequence number of the message.
int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change);

// Takes a subscription change message and returns the layers that have active
// subscriptions of the layers that are offered by your HAL client/publisher.
//
// A publisher can use this function when receiving a subscription change message
// to determine which layers to publish data on.
// The caller of this function can optionally decide to not consume these layers
// if the subscription change has the sequence number less than the last seen
// sequence number.
std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
                                          const VmsOffers& offers);

// Takes an availability change message and returns true if the parsed message implies that
// the service has newly started or restarted.
// If the message has a sequence number 0, it means that the service
// has newly started or restarted.
bool hasServiceNewlyStarted(const VehiclePropValue& availability_change);

}  // namespace vms
}  // namespace V2_0
+115 −12
Original line number Diff line number Diff line
@@ -27,16 +27,23 @@ namespace vms {

static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
static constexpr int kMessageTypeSize = 1;
static constexpr int kPublisherIdSize = 1;
static constexpr int kLayerNumberSize = 1;
static constexpr int kLayerSize = 3;
static constexpr int kLayerAndPublisherSize = 4;
static constexpr int kPublisherIdIndex =
        toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID);
static constexpr int kSubscriptionStateSequenceNumberIndex =
        toInt(VmsSubscriptionsStateIntegerValuesIndex::SEQUENCE_NUMBER);
static constexpr int kAvailabilitySequenceNumberIndex =
        toInt(VmsAvailabilityStateIntegerValuesIndex::SEQUENCE_NUMBER);

// TODO(aditin): We should extend the VmsMessageType enum to include a first and
// last, which would prevent breakages in this API. However, for all of the
// functions in this module, we only need to guarantee that the message type is
// between SUBSCRIBE and DATA.
// between SUBSCRIBE and PUBLISHER_ID_RESPONSE.
static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
static constexpr int kLastMessageType = toInt(VmsMessageType::DATA);
static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE);

std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
    auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
@@ -77,17 +84,16 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
    return result;
}

std::unique_ptr<VehiclePropValue> createOfferingMessage(
    const std::vector<VmsLayerOffering>& offering) {
    int message_size = kMessageTypeSize + kLayerNumberSize;
    for (const auto& offer : offering) {
        message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers) {
    int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize;
    for (const auto& offer : offers.offerings) {
        message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize);
    }
    auto result = createBaseVmsMessage(message_size);

    std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
                                   static_cast<int>(offering.size())};
    for (const auto& offer : offering) {
    std::vector<int32_t> offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id,
                                      static_cast<int>(offers.offerings.size())};
    for (const auto& offer : offers.offerings) {
        std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
                                             offer.layer.version,
                                             static_cast<int32_t>(offer.dependencies.size())};
@@ -97,9 +103,9 @@ std::unique_ptr<VehiclePropValue> createOfferingMessage(
            layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
                                dependency_layer.end());
        }
        offers.insert(offers.end(), layer_vector.begin(), layer_vector.end());
        offerings.insert(offerings.end(), layer_vector.begin(), layer_vector.end());
    }
    result->value.int32Values = offers;
    result->value.int32Values = offerings;
    return result;
}

@@ -153,6 +159,103 @@ std::string parseData(const VehiclePropValue& value) {
    }
}

std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
        const std::string& vms_provider_description) {
    auto result = createBaseVmsMessage(kMessageTypeSize);
    result->value.int32Values = hidl_vec<int32_t>{
            toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
    };
    result->value.bytes =
            std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
    return result;
}

int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) {
    if (isValidVmsMessage(publisher_id_response) &&
        parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE &&
        publisher_id_response.value.int32Values.size() > kPublisherIdIndex) {
        return publisher_id_response.value.int32Values[kPublisherIdIndex];
    }
    return -1;
}

bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
                           const int last_seen_sequence_number) {
    return (isValidVmsMessage(subscription_change) &&
            parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
            subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
            subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
                    last_seen_sequence_number);
}

int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) {
    if (isValidVmsMessage(subscription_change) &&
        parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
        subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
        return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex];
    }
    return -1;
}

std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
                                          const VmsOffers& offers) {
    if (isValidVmsMessage(subscription_change) &&
        parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
        subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
        const int32_t num_of_layers = subscription_change.value.int32Values[toInt(
                VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
        const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt(
                VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];

        std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
        for (const auto& offer : offers.offerings) {
            offered_layers.insert(offer.layer);
        }
        std::vector<VmsLayer> subscribed_layers;

        int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
        // Add all subscribed layers which are offered by the current publisher.
        for (int i = 0; i < num_of_layers; i++) {
            VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
                                      subscription_change.value.int32Values[current_index + 1],
                                      subscription_change.value.int32Values[current_index + 2]);
            if (offered_layers.find(layer) != offered_layers.end()) {
                subscribed_layers.push_back(layer);
            }
            current_index += kLayerSize;
        }
        // Add all subscribed associated layers which are offered by the current publisher.
        // For this, we need to check if the associated layer has a publisher ID which is
        // same as that of the current publisher.
        for (int i = 0; i < num_of_associated_layers; i++) {
            VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
                                      subscription_change.value.int32Values[current_index + 1],
                                      subscription_change.value.int32Values[current_index + 2]);
            current_index += kLayerSize;
            if (offered_layers.find(layer) != offered_layers.end()) {
                int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index];
                current_index++;
                for (int j = 0; j < num_of_publisher_ids; j++) {
                    if (subscription_change.value.int32Values[current_index] ==
                        offers.publisher_id) {
                        subscribed_layers.push_back(layer);
                    }
                    current_index++;
                }
            }
        }
        return subscribed_layers;
    }
    return {};
}

bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) {
    return (isValidVmsMessage(availability_change) &&
            parseMessageType(availability_change) == VmsMessageType::AVAILABILITY_CHANGE &&
            availability_change.value.int32Values.size() > kAvailabilitySequenceNumberIndex &&
            availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0);
}

}  // namespace vms
}  // namespace V2_0
}  // namespace vehicle
+0 −1
Original line number Diff line number Diff line
@@ -278,7 +278,6 @@ TEST_F(VehicleHalManagerTest, subscribe) {

    cb->reset();
    VehiclePropValue actualValue(*subscribedValue.get());
    actualValue.status = VehiclePropertyStatus::AVAILABLE;
    hal->sendPropEvent(std::move(subscribedValue));

    ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
+178 −19
Original line number Diff line number Diff line
@@ -60,52 +60,64 @@ TEST(VmsUtilsTest, unsubscribeMessage) {
}

TEST(VmsUtilsTest, singleOfferingMessage) {
    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
    auto message = createOfferingMessage(offering);
    VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 2))}};
    auto message = createOfferingMessage(offers);
    ASSERT_NE(message, nullptr);
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
    EXPECT_EQ(message->value.int32Values.size(), 0x6ul);
    EXPECT_EQ(message->value.int32Values.size(), 0x7ul);
    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);

    // Publisher ID
    EXPECT_EQ(message->value.int32Values[1], 123);

    // Number of layer offerings
    EXPECT_EQ(message->value.int32Values[1], 1);
    EXPECT_EQ(message->value.int32Values[2], 1);

    // Layer
    EXPECT_EQ(message->value.int32Values[2], 1);
    EXPECT_EQ(message->value.int32Values[3], 0);
    EXPECT_EQ(message->value.int32Values[4], 2);
    EXPECT_EQ(message->value.int32Values[3], 1);
    EXPECT_EQ(message->value.int32Values[4], 0);
    EXPECT_EQ(message->value.int32Values[5], 2);

    // Number of dependencies
    EXPECT_EQ(message->value.int32Values[5], 0);
    EXPECT_EQ(message->value.int32Values[6], 0);
}

TEST(VmsUtilsTest, offeringWithDependencies) {
    VmsLayer layer(1, 0, 2);
    std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)};
    std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)};
    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
    auto message = createOfferingMessage(offering);
    VmsOffers offers = {123, offering};
    auto message = createOfferingMessage(offers);
    ASSERT_NE(message, nullptr);
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
    EXPECT_EQ(message->value.int32Values.size(), 0x9ul);
    EXPECT_EQ(message->value.int32Values.size(), 0xdul);
    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);

    // Publisher ID
    EXPECT_EQ(message->value.int32Values[1], 123);

    // Number of layer offerings
    EXPECT_EQ(message->value.int32Values[1], 1);
    EXPECT_EQ(message->value.int32Values[2], 1);

    // Layer
    EXPECT_EQ(message->value.int32Values[2], 1);
    EXPECT_EQ(message->value.int32Values[3], 0);
    EXPECT_EQ(message->value.int32Values[4], 2);
    EXPECT_EQ(message->value.int32Values[3], 1);
    EXPECT_EQ(message->value.int32Values[4], 0);
    EXPECT_EQ(message->value.int32Values[5], 2);

    // Number of dependencies
    EXPECT_EQ(message->value.int32Values[5], 1);
    EXPECT_EQ(message->value.int32Values[6], 2);

    // Dependency 1
    EXPECT_EQ(message->value.int32Values[6], 2);
    EXPECT_EQ(message->value.int32Values[7], 0);
    EXPECT_EQ(message->value.int32Values[8], 2);
    EXPECT_EQ(message->value.int32Values[7], 2);
    EXPECT_EQ(message->value.int32Values[8], 0);
    EXPECT_EQ(message->value.int32Values[9], 2);

    // Dependency 2
    EXPECT_EQ(message->value.int32Values[10], 3);
    EXPECT_EQ(message->value.int32Values[11], 0);
    EXPECT_EQ(message->value.int32Values[12], 3);
}

TEST(VmsUtilsTest, availabilityMessage) {
@@ -166,6 +178,153 @@ TEST(VmsUtilsTest, parseInvalidDataMessage) {
    EXPECT_TRUE(data_str.empty());
}

TEST(VmsUtilsTest, publisherIdRequest) {
    std::string bytes = "pub_id";
    auto message = createPublisherIdRequest(bytes);
    ASSERT_NE(message, nullptr);
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
    EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
    EXPECT_EQ(parseMessageType(*message), VmsMessageType::PUBLISHER_ID_REQUEST);
    EXPECT_EQ(message->value.bytes.size(), bytes.size());
    EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
}

TEST(VmsUtilsTest, validPublisherIdResponse) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), 1234};
    EXPECT_EQ(parsePublisherIdResponse(*message), 1234);
}

TEST(VmsUtilsTest, invalidPublisherIdResponse) {
    auto message = createBaseVmsMessage(1);
    EXPECT_EQ(parsePublisherIdResponse(*message), -1);
}

TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsState) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
    EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234);
}

TEST(VmsUtilsTest, invalidSubscriptionsState) {
    auto message = createBaseVmsMessage(1);
    EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), -1);
}

TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumber) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
    EXPECT_TRUE(isSequenceNumberNewer(*message, 1233));
}

TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumber) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
    EXPECT_FALSE(isSequenceNumberNewer(*message, 1235));
}

TEST(VmsUtilsTest, newSequenceNumberForSameNumber) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
    EXPECT_FALSE(isSequenceNumberNewer(*message, 1234));
}

TEST(VmsUtilsTest, subscribedLayers) {
    VmsOffers offers = {123,
                        {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
                         VmsLayerOffering(VmsLayer(2, 0, 1))}};
    auto message = createBaseVmsMessage(2);
    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
                                                   1234,  // sequence number
                                                   2,     // number of layers
                                                   1,     // number of associated layers
                                                   1,     // layer 1
                                                   0,
                                                   1,
                                                   4,  // layer 2
                                                   1,
                                                   1,
                                                   2,  // associated layer
                                                   0,
                                                   1,
                                                   2,    // number of publisher IDs
                                                   111,  // publisher IDs
                                                   123};
    EXPECT_TRUE(isValidVmsMessage(*message));
    auto result = getSubscribedLayers(*message, offers);
    EXPECT_EQ(static_cast<int>(result.size()), 2);
    EXPECT_EQ(result.at(0), VmsLayer(1, 0, 1));
    EXPECT_EQ(result.at(1), VmsLayer(2, 0, 1));
}

TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtype) {
    VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
    auto message = createBaseVmsMessage(2);
    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
                                                   1234,  // sequence number
                                                   1,     // number of layers
                                                   0,     // number of associated layers
                                                   1,     // layer 1
                                                   1,     // different subtype
                                                   1};
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}

TEST(VmsUtilsTest, subscribedLayersWithDifferentVersion) {
    VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
    auto message = createBaseVmsMessage(2);
    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
                                                   1234,  // sequence number
                                                   1,     // number of layers
                                                   0,     // number of associated layers
                                                   1,     // layer 1
                                                   0,
                                                   2};  // different version
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}

TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherId) {
    VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
    auto message = createBaseVmsMessage(2);
    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
                                                   1234,  // sequence number
                                                   0,     // number of layers
                                                   1,     // number of associated layers
                                                   1,     // associated layer 1
                                                   0,
                                                   1,
                                                   1,     // number of publisher IDs
                                                   234};  // publisher ID 1
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}

TEST(VmsUtilsTest, serviceNewlyStarted) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 0};
    EXPECT_TRUE(hasServiceNewlyStarted(*message));
}

TEST(VmsUtilsTest, serviceNotNewlyStarted) {
    auto message = createBaseVmsMessage(2);
    message->value.int32Values =
            hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
    EXPECT_FALSE(hasServiceNewlyStarted(*message));
}

TEST(VmsUtilsTest, invalidAvailabilityChange) {
    auto message = createBaseVmsMessage(1);
    EXPECT_FALSE(hasServiceNewlyStarted(*message));
}

}  // namespace

}  // namespace vms