512 lines
23 KiB
C++
512 lines
23 KiB
C++
/*
|
|
* Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
* A copy of the License is located at
|
|
*
|
|
* http://aws.amazon.com/apache2.0/
|
|
*
|
|
* or in the "license" file accompanying this file. This file 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 <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <AVSCommon/Utils/Logger/Logger.h>
|
|
#include <AVSCommon/Utils/WaitEvent.h>
|
|
|
|
#include "ContextManager/ContextManager.h"
|
|
|
|
using namespace testing;
|
|
|
|
namespace alexaClientSDK {
|
|
namespace contextManager {
|
|
namespace test {
|
|
|
|
using namespace avsCommon;
|
|
using namespace avsCommon::avs;
|
|
using namespace avsCommon::sdkInterfaces;
|
|
|
|
/// String to identify log entries originating from this file.
|
|
static const std::string TAG("ContextManagerTest");
|
|
|
|
/**
|
|
* Create a LogEntry using this file's TAG and the specified event string.
|
|
*
|
|
* @param The event string for this @c LogEntry.
|
|
*/
|
|
#define LX(event) alexaClientSDK::avsCommon::utils::logger::LogEntry(TAG, event)
|
|
|
|
/// Mock state provider.
|
|
class MockStateProvider : public StateProviderInterface {
|
|
public:
|
|
MOCK_METHOD2(
|
|
provideState,
|
|
void(const avs::CapabilityTag& stateProviderName, const ContextRequestToken stateRequestToken));
|
|
};
|
|
|
|
/// Mock legacy state provider.
|
|
struct MockLegacyStateProvider : public StateProviderInterface {
|
|
MOCK_METHOD2(
|
|
provideState,
|
|
void(const avs::NamespaceAndName& stateProviderName, const ContextRequestToken stateRequestToken));
|
|
};
|
|
|
|
/// Mock context requester.
|
|
struct MockContextRequester : public ContextRequesterInterface {
|
|
MOCK_METHOD3(
|
|
onContextAvailable,
|
|
void(const std::string& endpointId, const avs::AVSContext& endpointContext, ContextRequestToken requestToken));
|
|
MOCK_METHOD2(onContextFailure, void(const ContextRequestError error, ContextRequestToken token));
|
|
};
|
|
|
|
/// Mock context observer.
|
|
struct MockContextObserver : public ContextManagerObserverInterface {
|
|
MOCK_METHOD3(
|
|
onStateChanged,
|
|
void(const avs::CapabilityTag& identifier, const avs::CapabilityState& state, AlexaStateChangeCauseType cause));
|
|
};
|
|
|
|
/// Context Manager Test
|
|
class ContextManagerTest : public ::testing::Test {
|
|
protected:
|
|
/**
|
|
* Creates a @c ContextManager.
|
|
*/
|
|
void SetUp() override;
|
|
|
|
/// @c ContextManager to test
|
|
std::shared_ptr<ContextManagerInterface> m_contextManager;
|
|
};
|
|
|
|
void ContextManagerTest::SetUp() {
|
|
auto deviceInfo =
|
|
avsCommon::utils::DeviceInfo::create("clientId", "productId", "1234", "manufacturer", "my device");
|
|
ASSERT_NE(deviceInfo, nullptr);
|
|
|
|
m_contextManager = ContextManager::create(*deviceInfo);
|
|
}
|
|
|
|
/**
|
|
* Set the state with a @c StateRefreshPolicy @c ALWAYS for a @c StateProviderInterface that is registered with the
|
|
* @c ContextManager. Expect @c SetStateResult @c SUCCESS is returned.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_setStateForLegacyRegisteredProvider) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
std::string payload{R"({"state":"value"})"};
|
|
ASSERT_EQ(m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS), SetStateResult::SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* Set the state with a @c StateRefreshPolicy @c NEVER for a @c StateProviderInterface that is not registered with the
|
|
* @c ContextManager. Expect @c SetStateResult @c SUCCESS is returned.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_setStateForUnregisteredLegacyProvider) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
std::string payload{R"({"state":"value"})"};
|
|
ASSERT_EQ(m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS), SetStateResult::SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* Set the states with a @c StateRefreshPolicy @c ALWAYS for @c StateProviderInterfaces that are registered with the
|
|
* @c ContextManager. Request for context by calling @c getContext. Expect that the context is returned within the
|
|
* timeout period. Check the context that is returned by the @c ContextManager. Expect it should match the test value.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_getContextLegacyProvider) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
std::string payload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
std::promise<ContextRequestToken> tokenPromise;
|
|
EXPECT_CALL(*provider, provideState(_, _))
|
|
.WillOnce(
|
|
WithArg<1>(Invoke([&tokenPromise](const ContextRequestToken token) { tokenPromise.set_value(token); })));
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise](const AVSContext& context) {
|
|
contextStatesPromise.set_value(context.getStates());
|
|
})));
|
|
|
|
auto requestToken = m_contextManager->getContext(requester);
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
auto expectedTokenFuture = tokenPromise.get_future();
|
|
ASSERT_EQ(expectedTokenFuture.wait_for(timeout), std::future_status::ready);
|
|
EXPECT_EQ(requestToken, expectedTokenFuture.get());
|
|
|
|
ASSERT_EQ(
|
|
m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS, requestToken),
|
|
SetStateResult::SUCCESS);
|
|
|
|
auto statesFuture = contextStatesPromise.get_future();
|
|
ASSERT_EQ(statesFuture.wait_for(timeout), std::future_status::ready);
|
|
EXPECT_EQ(statesFuture.get()[capability].valuePayload, payload);
|
|
}
|
|
|
|
/**
|
|
* Respond to the same state request twice. The first one should succeed while the second one should fail.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_setLegacyStateProviderSetStateTwiceShouldFail) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
std::string payload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*provider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
utils::WaitEvent stateAvailableEvent;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _)).WillOnce((InvokeWithoutArgs([&stateAvailableEvent] {
|
|
stateAvailableEvent.wakeUp();
|
|
})));
|
|
|
|
auto requestToken = m_contextManager->getContext(requester);
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
ASSERT_TRUE(provideStateEvent.wait(timeout));
|
|
|
|
ASSERT_EQ(
|
|
m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS, requestToken),
|
|
SetStateResult::SUCCESS);
|
|
|
|
ASSERT_TRUE(stateAvailableEvent.wait(timeout));
|
|
EXPECT_EQ(
|
|
m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS, requestToken),
|
|
SetStateResult::STATE_TOKEN_OUTDATED);
|
|
}
|
|
|
|
/**
|
|
* Register a @c StateProviderInterfaces with the @c ContextManager which responds slowly to @provideState requests.
|
|
* Set the states with a @c StateRefreshPolicy @c ALWAYS for @c StateProviderInterfaces. Request for context by calling
|
|
* @c getContext. Expect that failure occurs due to timeout.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_provideStateTimeout) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
std::string payload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*provider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
auto token = m_contextManager->getContext(requester, capability.endpointId, timeout);
|
|
|
|
utils::WaitEvent stateFailureEvent;
|
|
EXPECT_CALL(*requester, onContextFailure(ContextRequestError::STATE_PROVIDER_TIMEDOUT, token))
|
|
.WillOnce((InvokeWithoutArgs([&stateFailureEvent] { stateFailureEvent.wakeUp(); })));
|
|
|
|
ASSERT_TRUE(provideStateEvent.wait(timeout));
|
|
ASSERT_TRUE(stateFailureEvent.wait(timeout + timeout));
|
|
}
|
|
|
|
/**
|
|
* Request for context by calling @c getContextSet. Wait for context. Set the state for a @c StateProviderInterface
|
|
* that is registered with the @c ContextManager with a wrong token value. Expect that
|
|
* @c SetStateResult @c STATE_TOKEN_OUTDATED is returned.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_incorrectToken) {
|
|
auto provider = std::make_shared<MockLegacyStateProvider>();
|
|
auto capability = NamespaceAndName("Namespace", "Name");
|
|
std::string payload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*provider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
auto requestToken = m_contextManager->getContext(requester);
|
|
const std::chrono::milliseconds timeout{100};
|
|
ASSERT_TRUE(provideStateEvent.wait(timeout));
|
|
|
|
EXPECT_EQ(
|
|
m_contextManager->setState(capability, payload, StateRefreshPolicy::ALWAYS, requestToken + 1),
|
|
SetStateResult::STATE_TOKEN_OUTDATED);
|
|
}
|
|
|
|
/**
|
|
* Set the states with a @c StateRefreshPolicy @c ALWAYS for @c StateProviderInterfaces that are registered with the
|
|
* @c ContextManager. Request for context by calling @c getContext. Expect that the context is returned within the
|
|
* timeout period.
|
|
*
|
|
* There's a dummyProvider with StateRefreshPolicy @c SOMETIMES that returns an empty context. Check ContextManager is
|
|
* okay with it and would include the context provided by the dummyProvider.
|
|
*
|
|
* Check the context that is returned by the @c ContextManager. Expect it should match the test value.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_sometimesProvider) {
|
|
auto sometimesProvider = std::make_shared<MockLegacyStateProvider>();
|
|
auto sometimesCapability = NamespaceAndName("Namespace", "Name");
|
|
std::string sometimesPayload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(sometimesCapability, sometimesProvider);
|
|
|
|
ASSERT_EQ(
|
|
m_contextManager->setState(sometimesCapability, sometimesPayload, StateRefreshPolicy::SOMETIMES),
|
|
SetStateResult::SUCCESS);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*sometimesProvider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise](const AVSContext& context) {
|
|
contextStatesPromise.set_value(context.getStates());
|
|
})));
|
|
|
|
auto requestToken = m_contextManager->getContext(requester);
|
|
const std::chrono::milliseconds timeout{100};
|
|
provideStateEvent.wait(timeout);
|
|
ASSERT_EQ(
|
|
m_contextManager->setState(sometimesCapability, "", StateRefreshPolicy::SOMETIMES, requestToken),
|
|
SetStateResult::SUCCESS);
|
|
|
|
auto statesFuture = contextStatesPromise.get_future();
|
|
ASSERT_EQ(statesFuture.wait_for(timeout), std::future_status::ready);
|
|
EXPECT_EQ(statesFuture.get()[sometimesCapability].valuePayload, sometimesPayload);
|
|
}
|
|
|
|
/**
|
|
* Test that a provider that sets its policy to NEVER is not queried but that the state is included in the context.
|
|
*/
|
|
TEST_F(ContextManagerTest, test_neverProvider) {
|
|
auto neverProvider = std::make_shared<StrictMock<MockLegacyStateProvider>>();
|
|
auto neverCapability = NamespaceAndName("Namespace", "Name");
|
|
std::string neverPayload{R"({"state":"value"})"};
|
|
m_contextManager->setStateProvider(neverCapability, neverProvider);
|
|
|
|
ASSERT_EQ(
|
|
m_contextManager->setState(neverCapability, neverPayload, StateRefreshPolicy::NEVER), SetStateResult::SUCCESS);
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise](const AVSContext& context) {
|
|
contextStatesPromise.set_value(context.getStates());
|
|
})));
|
|
|
|
m_contextManager->getContext(requester);
|
|
const std::chrono::milliseconds timeout{100};
|
|
|
|
auto statesFuture = contextStatesPromise.get_future();
|
|
ASSERT_EQ(statesFuture.wait_for(timeout), std::future_status::ready);
|
|
EXPECT_EQ(statesFuture.get()[neverCapability].valuePayload, neverPayload);
|
|
}
|
|
|
|
/// Test that only context relevant to the given endpoint is included in the getContext.
|
|
TEST_F(ContextManagerTest, test_getEndpointContextShouldIncludeOnlyRelevantStates) {
|
|
// Capability that belongs to the target endpoint.
|
|
auto providerForTargetEndpoint = std::make_shared<MockStateProvider>();
|
|
auto capabilityForTarget = CapabilityTag("TargetNamespace", "TargetName", "TargetEndpointId");
|
|
CapabilityState stateForTarget{R"({"state":"target"})"};
|
|
m_contextManager->setStateProvider(capabilityForTarget, providerForTargetEndpoint);
|
|
|
|
// Capability that belongs to another endpoint.
|
|
auto providerForOtherEndpoint = std::make_shared<StrictMock<MockStateProvider>>();
|
|
auto capabilityForOther = CapabilityTag("OtherNamespace", "OtherName", "OtherEndpointId");
|
|
m_contextManager->setStateProvider(capabilityForOther, providerForOtherEndpoint);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*providerForTargetEndpoint, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise](const AVSContext& context) {
|
|
contextStatesPromise.set_value(context.getStates());
|
|
})));
|
|
|
|
// Get context for the target endpoint.
|
|
auto requestToken = m_contextManager->getContext(requester, capabilityForTarget.endpointId);
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
provideStateEvent.wait(timeout);
|
|
m_contextManager->provideStateResponse(capabilityForTarget, stateForTarget, requestToken);
|
|
|
|
auto statesFuture = contextStatesPromise.get_future();
|
|
ASSERT_EQ(statesFuture.wait_for(timeout), std::future_status::ready);
|
|
|
|
auto states = statesFuture.get();
|
|
EXPECT_EQ(states[capabilityForTarget].valuePayload, stateForTarget.valuePayload);
|
|
EXPECT_EQ(states.find(capabilityForOther), states.end());
|
|
}
|
|
|
|
/// Test that requester will get notified of a failure when one provider was not able to provide its state.
|
|
TEST_F(ContextManagerTest, test_getContextWhenStateAndCacheAreUnavailableShouldFail) {
|
|
auto provider = std::make_shared<MockStateProvider>();
|
|
auto capability = CapabilityTag("Namespace", "Name", "EndpointId");
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*provider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
// Get context.
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
auto requestToken = m_contextManager->getContext(requester, capability.endpointId);
|
|
|
|
// Expect failure.
|
|
utils::WaitEvent contextFailureEvent;
|
|
EXPECT_CALL(*requester, onContextFailure(ContextRequestError::BUILD_CONTEXT_ERROR, requestToken))
|
|
.WillOnce(InvokeWithoutArgs([&contextFailureEvent] { contextFailureEvent.wakeUp(); }));
|
|
|
|
// Respond that state is unavailable after state has been requested.
|
|
const std::chrono::milliseconds timeout{100};
|
|
ASSERT_TRUE(provideStateEvent.wait(timeout));
|
|
m_contextManager->provideStateUnavailableResponse(capability, requestToken, false);
|
|
|
|
// Wait for failure.
|
|
EXPECT_TRUE(contextFailureEvent.wait(timeout));
|
|
}
|
|
|
|
/// Test that requester will get cached value when provider cannot provide latest state.
|
|
TEST_F(ContextManagerTest, test_getContextWhenStateUnavailableShouldReturnCache) {
|
|
auto provider = std::make_shared<MockStateProvider>();
|
|
auto capability = CapabilityTag("Namespace", "Name", "EndpointId");
|
|
CapabilityState state{R"({"state":"target"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
// Set value in the cache.
|
|
m_contextManager->reportStateChange(capability, state, AlexaStateChangeCauseType::APP_INTERACTION);
|
|
|
|
utils::WaitEvent provideStateEvent;
|
|
EXPECT_CALL(*provider, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent] {
|
|
provideStateEvent.wakeUp();
|
|
})));
|
|
|
|
// Get context.
|
|
auto requester = std::make_shared<MockContextRequester>();
|
|
auto requestToken = m_contextManager->getContext(requester, capability.endpointId);
|
|
|
|
std::promise<AVSContext::States> contextStatesPromise;
|
|
EXPECT_CALL(*requester, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise](const AVSContext& context) {
|
|
contextStatesPromise.set_value(context.getStates());
|
|
})));
|
|
|
|
// Respond that state is unavailable after state has been requested.
|
|
const std::chrono::milliseconds timeout{100};
|
|
ASSERT_TRUE(provideStateEvent.wait(timeout));
|
|
m_contextManager->provideStateUnavailableResponse(capability, requestToken, false);
|
|
|
|
// Wait for failure.
|
|
auto statesFuture = contextStatesPromise.get_future();
|
|
ASSERT_EQ(statesFuture.wait_for(timeout), std::future_status::ready);
|
|
EXPECT_EQ(statesFuture.get()[capability].valuePayload, state.valuePayload);
|
|
}
|
|
|
|
/// Test that report state change notifies the @c ContextManagerObserverInterface.
|
|
TEST_F(ContextManagerTest, test_reportStateChangeShouldNotifyObserver) {
|
|
// Add provider.
|
|
auto provider = std::make_shared<MockStateProvider>();
|
|
auto capability = CapabilityTag("Namespace", "Name", "EndpointId");
|
|
CapabilityState state{R"({"state":"target"})"};
|
|
m_contextManager->setStateProvider(capability, provider);
|
|
|
|
// Add observer.
|
|
auto observer = std::make_shared<MockContextObserver>();
|
|
m_contextManager->addContextManagerObserver(observer);
|
|
|
|
utils::WaitEvent notificationEvent;
|
|
auto cause = AlexaStateChangeCauseType::APP_INTERACTION;
|
|
EXPECT_CALL(*observer, onStateChanged(capability, state, cause)).WillOnce(InvokeWithoutArgs([¬ificationEvent] {
|
|
notificationEvent.wakeUp();
|
|
}));
|
|
|
|
// Report change.
|
|
m_contextManager->reportStateChange(capability, state, cause);
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
EXPECT_TRUE(notificationEvent.wait(timeout));
|
|
}
|
|
|
|
/// Test that getContext can handle multiple getContext at the same time.
|
|
TEST_F(ContextManagerTest, test_getContextInParallelShouldSucceed) {
|
|
// Capability that belongs to the first endpoint.
|
|
auto providerForEndpoint1 = std::make_shared<MockStateProvider>();
|
|
auto capabilityForEndpoint1 = CapabilityTag("Namespace", "Name", "EndpointId1");
|
|
CapabilityState stateForEndpoint1{R"({"state":1})"};
|
|
m_contextManager->setStateProvider(capabilityForEndpoint1, providerForEndpoint1);
|
|
|
|
// Capability that belongs to the second endpoint.
|
|
auto providerForEndpoint2 = std::make_shared<MockStateProvider>();
|
|
auto capabilityForEndpoint2 = CapabilityTag("Namespace", "Name", "EndpointId2");
|
|
CapabilityState stateForEndpoint2{R"({"state":2})"};
|
|
m_contextManager->setStateProvider(capabilityForEndpoint2, providerForEndpoint2);
|
|
|
|
// Expect both provide state calls
|
|
utils::WaitEvent provideStateEvent1;
|
|
EXPECT_CALL(*providerForEndpoint1, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent1] {
|
|
provideStateEvent1.wakeUp();
|
|
})));
|
|
utils::WaitEvent provideStateEvent2;
|
|
EXPECT_CALL(*providerForEndpoint2, provideState(_, _)).WillOnce((InvokeWithoutArgs([&provideStateEvent2] {
|
|
provideStateEvent2.wakeUp();
|
|
})));
|
|
|
|
// Expect both context to be available
|
|
auto requester1 = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise1;
|
|
EXPECT_CALL(*requester1, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise1](const AVSContext& context) {
|
|
contextStatesPromise1.set_value(context.getStates());
|
|
})));
|
|
auto requester2 = std::make_shared<MockContextRequester>();
|
|
std::promise<AVSContext::States> contextStatesPromise2;
|
|
EXPECT_CALL(*requester2, onContextAvailable(_, _, _))
|
|
.WillOnce(WithArg<1>(Invoke([&contextStatesPromise2](const AVSContext& context) {
|
|
contextStatesPromise2.set_value(context.getStates());
|
|
})));
|
|
|
|
// Get context for both endpoints.
|
|
auto requestToken1 = m_contextManager->getContext(requester1, capabilityForEndpoint1.endpointId);
|
|
auto requestToken2 = m_contextManager->getContext(requester2, capabilityForEndpoint2.endpointId);
|
|
|
|
const std::chrono::milliseconds timeout{100};
|
|
ASSERT_TRUE(provideStateEvent1.wait(timeout));
|
|
ASSERT_TRUE(provideStateEvent2.wait(timeout));
|
|
m_contextManager->provideStateResponse(capabilityForEndpoint1, stateForEndpoint1, requestToken1);
|
|
m_contextManager->provideStateResponse(capabilityForEndpoint2, stateForEndpoint2, requestToken2);
|
|
|
|
// Validate that context for endpoint 1 only has its own capability state.
|
|
auto statesFuture1 = contextStatesPromise1.get_future();
|
|
ASSERT_EQ(statesFuture1.wait_for(timeout), std::future_status::ready);
|
|
auto statesForEndpoint1 = statesFuture1.get();
|
|
EXPECT_EQ(statesForEndpoint1[capabilityForEndpoint1].valuePayload, stateForEndpoint1.valuePayload);
|
|
EXPECT_EQ(statesForEndpoint1.find(capabilityForEndpoint2), statesForEndpoint1.end());
|
|
|
|
// Validate that context for endpoint 2 only has its own capability state.
|
|
auto statesFuture2 = contextStatesPromise2.get_future();
|
|
ASSERT_EQ(statesFuture2.wait_for(timeout), std::future_status::ready);
|
|
auto statesForEndpoint2 = statesFuture2.get();
|
|
EXPECT_EQ(statesForEndpoint2[capabilityForEndpoint2].valuePayload, stateForEndpoint2.valuePayload);
|
|
EXPECT_EQ(statesForEndpoint2.find(capabilityForEndpoint1), statesForEndpoint2.end());
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace contextManager
|
|
} // namespace alexaClientSDK
|