add standalone wdm update test support
diff --git a/src/test-apps/Makefile.am b/src/test-apps/Makefile.am
index 34b0ad8..fc490a6 100644
--- a/src/test-apps/Makefile.am
+++ b/src/test-apps/Makefile.am
@@ -116,6 +116,8 @@
MockWdmTestVerifier.h \
MockWdmViewClient.h \
MockWdmViewServer.h \
+ MockWdmUpdateServer.h \
+ MockWdmUpdateClient.h \
PASEEngineTest.h \
TAKEOptions.h \
TapAddrAutoconf.h \
@@ -1033,6 +1035,7 @@
happy/tests/standalone/wdmNext/test_weave_wdm_next_oneway_resub.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_mutual_resub.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_subless_notify_01.py \
+ happy/tests/standalone/wdmNext/test_weave_wdm_next_standalone_update_01.py \
$(NULL)
endif # WEAVE_RUN_HAPPY_WDM
@@ -1418,6 +1421,8 @@
MockWdmNodeOptions.cpp \
MockWdmViewServer.cpp \
MockWdmViewClient.cpp \
+ MockWdmUpdateServer.cpp \
+ MockWdmUpdateClient.cpp \
MockWdmSubscriptionInitiator.cpp \
MockWdmTestVerifier.cpp \
MockWdmSubscriptionResponder.cpp \
@@ -1480,8 +1485,10 @@
schema/weave/trait/telemetry/NetworkWiFiTelemetryTrait.cpp \
MockWdmViewServer.cpp \
MockWdmViewClient.cpp \
+ MockWdmUpdateServer.cpp \
+ MockWdmUpdateClient.cpp \
MockWdmSubscriptionInitiator.cpp \
- MockWdmTestVerifier.cpp \
+ MockWdmTestVerifier.cpp \
MockWdmSubscriptionResponder.cpp \
MockWdmNodeOptions.cpp \
MockLoggingManager.cpp \
diff --git a/src/test-apps/MockSinkTraits.cpp b/src/test-apps/MockSinkTraits.cpp
index 5a93618..a7e1008 100644
--- a/src/test-apps/MockSinkTraits.cpp
+++ b/src/test-apps/MockSinkTraits.cpp
@@ -1690,6 +1690,41 @@
return err;
}
+WEAVE_ERROR LocaleSettingsTraitUpdatableDataSink::Mutate(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ static unsigned int whichLocale = 0;
+ int aMutation;
+ static const char * locales[] = { "en-US", "zh-TW", "ja-JP", "pl-PL", "zh-CN" };
+ PropertyPathHandle pathHandle = kNullPropertyPathHandle;
+
+ MOCK_strlcpy(mLocale, locales[whichLocale], sizeof(mLocale));
+ whichLocale = (whichLocale + 1) % (sizeof(locales)/sizeof(locales[0]));
+
+ aMutation = MockWdmNodeOptions::kMutation_OneLeaf;
+ // This trait instance only supports the OneLeaf and Root mutations.
+
+ switch (aMutation)
+ {
+ case MockWdmNodeOptions::kMutation_Root:
+ pathHandle = LocaleSettingsTrait::kPropertyHandle_Root;
+ break;
+
+ case MockWdmNodeOptions::kMutation_OneLeaf:
+ default:
+ aMutation = MockWdmNodeOptions::kMutation_OneLeaf;
+ pathHandle = LocaleSettingsTrait::kPropertyHandle_active_locale;
+ break;
+ }
+
+ WeaveLogDetail(DataManagement, "<set updated> in 0x%08x", pathHandle);
+
+exit:
+ WeaveLogDetail(DataManagement, "LocaleSettingsTrait mutated %s with error %d", MockWdmNodeOptions::GetMutationStrings()[aMutation], err);
+
+ return err;
+}
+
WEAVE_ERROR LocaleSettingsTraitUpdatableDataSink::GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey)
{
return WEAVE_END_OF_INPUT;
diff --git a/src/test-apps/MockSinkTraits.h b/src/test-apps/MockSinkTraits.h
index 1b1d506..0959bbe 100644
--- a/src/test-apps/MockSinkTraits.h
+++ b/src/test-apps/MockSinkTraits.h
@@ -68,7 +68,7 @@
WEAVE_ERROR Mutate(SubscriptionClient * apSubClient,
bool aIsConditional,
MockWdmNodeOptions::WdmUpdateMutation aMutation);
-
+ WEAVE_ERROR Mutate(void);
private:
WEAVE_ERROR SetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE;
WEAVE_ERROR GetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE;
diff --git a/src/test-apps/MockWdmNodeOptions.cpp b/src/test-apps/MockWdmNodeOptions.cpp
index b31fbc8..e8c1733 100644
--- a/src/test-apps/MockWdmNodeOptions.cpp
+++ b/src/test-apps/MockWdmNodeOptions.cpp
@@ -1,6 +1,6 @@
/*
*
- * Copyright (c) 2018 Google LLC.
+ * Copyright (c) 2019 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
* All rights reserved.
*
@@ -90,6 +90,8 @@
{ "wdm-update-conditionality", kArgumentRequired, kToolOpt_WdmUpdateConditionality },
{ "wdm-update-timing", kArgumentRequired, kToolOpt_WdmUpdateTiming },
{ "wdm-update-discard-on-error", kNoArgument, kToolOpt_WdmUpdateDiscardOnError },
+ { "wdm-simple-update-client", kNoArgument, kToolOpt_WdmSimpleUpdateClient },
+ { "wdm-simple-update-server", kNoArgument, kToolOpt_WdmSimpleUpdateServer },
#endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
{ NULL }
};
@@ -226,6 +228,12 @@
" after-sub: after the subscription has been established\n"
" Default is after-sub\n"
"\n"
+ " --wdm-simple-update-client\n"
+ " Initiate a simple WDM Next update client\n"
+ "\n"
+ " --wdm-simple-update-server\n"
+ " Initiate a simple WDM Next update server\n"
+ "\n"
" --wdm-update-discard-on-error\n"
" Tells the client to discard the paths on which SetUpdated was called in case of error\n"
"\n";
@@ -345,6 +353,22 @@
#endif
+ case kToolOpt_WdmSimpleUpdateClient:
+ if (0 != mWdmRoleInTest)
+ {
+ PrintArgError("%s: Mock device can only play one role in WDM tests (%s)\n", progName, arg);
+ return false;
+ }
+ mWdmRoleInTest = kToolOpt_WdmSimpleUpdateClient;
+ break;
+ case kToolOpt_WdmSimpleUpdateServer:
+ if (0 != mWdmRoleInTest)
+ {
+ PrintArgError("%s: Mock device can only play one role in WDM tests (%s)\n", progName, arg);
+ return false;
+ }
+ mWdmRoleInTest = kToolOpt_WdmSimpleUpdateServer;
+ break;
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmSimpleSublessNotifyClient:
if (0 != mWdmRoleInTest)
diff --git a/src/test-apps/MockWdmNodeOptions.h b/src/test-apps/MockWdmNodeOptions.h
index 4391717..997ac66 100644
--- a/src/test-apps/MockWdmNodeOptions.h
+++ b/src/test-apps/MockWdmNodeOptions.h
@@ -67,6 +67,8 @@
kToolOpt_WdmUpdateConditionality,
kToolOpt_WdmUpdateTiming,
kToolOpt_WdmUpdateDiscardOnError,
+ kToolOpt_WdmSimpleUpdateClient,
+ kToolOpt_WdmSimpleUpdateServer,
};
class MockWdmNodeOptions : public OptionSetBase
diff --git a/src/test-apps/MockWdmUpdateClient.cpp b/src/test-apps/MockWdmUpdateClient.cpp
new file mode 100644
index 0000000..b239ce7
--- /dev/null
+++ b/src/test-apps/MockWdmUpdateClient.cpp
@@ -0,0 +1,543 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * 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.
+ * 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.
+ */
+
+/**
+ * @file
+ * This file implements the Weave Data Management mock standalone Update client.
+ *
+ */
+
+#define WEAVE_CONFIG_ENABLE_LOG_FILE_LINE_FUNC_ON_ERROR 1
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif // __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <new>
+#include "MockWdmUpdateClient.h"
+#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
+#include <Weave/Core/WeaveError.h>
+#include <Weave/Core/WeaveSecurityMgr.h>
+#include <Weave/Support/CodeUtils.h>
+#include <Weave/Profiles/WeaveProfiles.h>
+#include <Weave/Support/TimeUtils.h>
+
+// We want and assume the default managed namespace is Current and that is, explicitly, the managed namespace this code desires.
+#include <Weave/Profiles/data-management/DataManagement.h>
+
+#include "MockSinkTraits.h"
+#include "MockSourceTraits.h"
+#include "TestGroupKeyStore.h"
+
+#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
+
+using namespace nl::Weave;
+using namespace nl::Weave::TLV;
+using namespace nl::Weave::Profiles;
+using namespace nl::Weave::Profiles::DataManagement;
+using namespace Weave::Trait::Locale;
+
+const nl::Weave::ExchangeContext::Timeout kResponseTimeoutMsec = 15000;
+const nl::Weave::ExchangeContext::Timeout kWRMPActiveRetransTimeoutMsec = 3000;
+const nl::Weave::ExchangeContext::Timeout kWRMPInitialRetransTimeoutMsec = 3000;
+const uint16_t kWRMPMaxRetrans = 3;
+const uint16_t kWRMPAckTimeoutMsec = 200;
+const uint16_t ksignatureType = 1;
+const nl::Weave::Profiles::Time::timesync_t kUpdateTimeoutMicroSecs = 30 * nl::kMicrosecondsPerSecond;
+
+
+static nl::Weave::WRMPConfig gWRMPConfig = { kWRMPInitialRetransTimeoutMsec, kWRMPActiveRetransTimeoutMsec, kWRMPAckTimeoutMsec, kWRMPMaxRetrans };
+
+/**
+ * Log the specified message in the form of @a aFormat.
+ *
+ * @param[in] aFormat A pointer to a NULL-terminated C string with
+ * C Standard Library-style format specifiers
+ * containing the log message to be formatted and
+ * logged.
+ * @param[in] ... An argument list whose elements should correspond
+ * to the format specifiers in @a aFormat.
+ *
+ */
+static void TLVPrettyPrinter(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+
+ // There is no proper Weave logging routine for us to use here
+ vprintf(aFormat, args);
+
+ va_end(args);
+}
+
+static WEAVE_ERROR DebugPrettyPrint(nl::Weave::TLV::TLVReader & aReader)
+{
+ return nl::Weave::TLV::Debug::Dump(aReader, TLVPrettyPrinter);
+}
+
+class WdmUpdateHelper {
+ public:
+ WdmUpdateHelper();
+ ~WdmUpdateHelper() { }
+
+ void Setup(Binding * const apBinding, void * const apAppState, UpdateClient::EventCallback const aEventCallback);
+ void TearDown();
+
+ WEAVE_ERROR UpdateAndSendLeaf(void);
+ WEAVE_ERROR UpdateAndSendRoot(void);
+
+ private:
+ UpdateClient mUpdateClient;
+ // The encoder
+ UpdateEncoder mEncoder;
+ UpdateEncoder::Context mContext;
+
+ // These are here for convenience
+ PacketBuffer *mBuf;
+ TraitPath mTP;
+
+ //
+ // The state usually held by the SubscriptionClient
+ //
+
+ // The list of path to encode
+ TraitPathStore mPathList;
+ TraitPathStore::Record mStorage[10];
+
+ // The Trait instances
+ LocaleSettingsTraitUpdatableDataSink mLocaleSettingsTraitUpdatableDataSink;
+
+ // The catalog
+ SingleResourceSinkTraitCatalog mSinkCatalog;
+ SingleResourceSinkTraitCatalog::CatalogItem mSinkCatalogStore[9];
+
+ // The set of TraitDataHandles assigned by the catalog
+ // to the Trait instances
+ enum
+ {
+ kLocaleSettingsSinkIndex,
+ kMaxNumTraitHandles,
+ };
+ TraitDataHandle mTraitHandleSet[kMaxNumTraitHandles];
+
+ void InitEncoderContext(void);
+
+};
+
+WdmUpdateHelper::WdmUpdateHelper() :
+ mBuf(NULL),
+ mSinkCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID),
+ mSinkCatalogStore, sizeof(mSinkCatalogStore) / sizeof(mSinkCatalogStore[0]))
+{
+ mPathList.Init(mStorage, ArraySize(mStorage));
+
+ mSinkCatalog.Add(0, &mLocaleSettingsTraitUpdatableDataSink, mTraitHandleSet[kLocaleSettingsSinkIndex]);
+
+ mLocaleSettingsTraitUpdatableDataSink.SetUpdateEncoder(&mEncoder);
+}
+
+void WdmUpdateHelper::Setup(Binding * const apBinding, void * const apAppState, UpdateClient::EventCallback const aEventCallback)
+{
+ mUpdateClient.Init(apBinding, apAppState, aEventCallback);
+ mPathList.Clear();
+ mLocaleSettingsTraitUpdatableDataSink.Mutate();
+}
+
+void WdmUpdateHelper::TearDown()
+{
+ if (mBuf != NULL)
+ {
+ PacketBuffer::Free(mBuf);
+ mBuf = 0;
+ }
+}
+
+void WdmUpdateHelper::InitEncoderContext(void)
+{
+ if (NULL == mBuf)
+ {
+ mBuf = PacketBuffer::New(0);
+ VerifyOrExit(mBuf != NULL, );
+ }
+
+ mBuf->SetDataLength(0);
+
+ mContext.mBuf = mBuf;
+ mContext.mMaxPayloadSize = mBuf->AvailableDataLength();
+ mContext.mUpdateRequestIndex = 7;
+ mContext.mExpiryTimeMicroSecond = 0;
+ mContext.mItemInProgress = 0;
+ mContext.mNextDictionaryElementPathHandle = kNullPropertyPathHandle;
+ mContext.mInProgressUpdateList = &mPathList;
+ mContext.mDataSinkCatalog = &mSinkCatalog;
+
+exit:
+ return;
+}
+
+WEAVE_ERROR WdmUpdateHelper::UpdateAndSendLeaf(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ mTP = {
+ mTraitHandleSet[kLocaleSettingsSinkIndex],
+ CreatePropertyPathHandle(LocaleSettingsTrait::kPropertyHandle_active_locale)
+ };
+
+ err = mPathList.AddItem(mTP);
+ SuccessOrExit(err);
+
+ InitEncoderContext();
+
+ err = mEncoder.EncodeRequest(mContext);
+ SuccessOrExit(err);
+ err = mUpdateClient.SendUpdate(false, mBuf, true);
+ mBuf = NULL;
+ SuccessOrExit(err);
+
+exit:
+ if (NULL != mBuf)
+ {
+ PacketBuffer::Free(mBuf);
+ mBuf = NULL;
+ }
+
+ if (err == WEAVE_ERROR_BUFFER_TOO_SMALL)
+ {
+ WeaveLogDetail(DataManagement, "illegal oversized trait property is too big to fit in the packet");
+ }
+
+ return err;
+}
+
+WEAVE_ERROR WdmUpdateHelper::UpdateAndSendRoot(void)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ mTP = {
+ mTraitHandleSet[kLocaleSettingsSinkIndex],
+ kRootPropertyPathHandle
+ };
+
+ err = mPathList.AddItem(mTP);
+ SuccessOrExit(err);
+
+ InitEncoderContext();
+
+ err = mEncoder.EncodeRequest(mContext);
+ SuccessOrExit(err);
+ err = mUpdateClient.SendUpdate(false, mBuf, true);
+ mBuf = NULL;
+ SuccessOrExit(err);
+
+exit:
+ if (NULL != mBuf)
+ {
+ PacketBuffer::Free(mBuf);
+ mBuf = NULL;
+ }
+
+ if (err == WEAVE_ERROR_BUFFER_TOO_SMALL)
+ {
+ WeaveLogDetail(DataManagement, "illegal oversized trait property is too big to fit in the packet");
+ }
+
+ return err;
+}
+
+class MockWdmUpdateClientImpl: public MockWdmUpdateClient
+{
+public:
+ MockWdmUpdateClientImpl();
+
+ virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, const char * const aTestCaseId, const int aTestSecurityMode,
+ const uint32_t aKeyId);
+
+ virtual WEAVE_ERROR StartTesting(const uint64_t aPublisherNodeId, const uint16_t aSubnetId);
+
+ WEAVE_ERROR SendUpdateRequest(void);
+
+private:
+ nl::Weave::WeaveExchangeManager *mExchangeMgr;
+ uint64_t mPublisherNodeId;
+ uint16_t mPublisherSubnetId;
+ Binding * mBinding;
+ WdmUpdateHelper mWdmUpdateHelper;
+
+ WEAVE_ERROR PrepareBinding(void);
+
+ int mTestCaseId;
+ int mTestSecurityMode;
+ uint32_t mKeyId;
+ TraitPath mTraitPaths[1];
+
+ static void EventCallback (void * const aAppState, UpdateClient::EventType aEvent, const UpdateClient::InEventParam & aInParam, UpdateClient::OutEventParam & aOutParam);
+
+ static WEAVE_ERROR AddArgumentCallback(UpdateClient * apClient, void * const aAppState, nl::Weave::TLV::TLVWriter &aOutWriter);
+
+ enum {
+ kLocaleSettingsSinkIndex = 0,
+ };
+
+ LocaleSettingsTraitDataSink mLocaleSettingsTraitDataSink;
+ SingleResourceSinkTraitCatalog mSinkCatalog;
+ SingleResourceTraitCatalog<TraitDataSink>::CatalogItem mSinkCatalogStore[1];
+
+ static void BindingEventCallback (void * const apAppState, const nl::Weave::Binding::EventType aEvent,
+ const nl::Weave::Binding::InEventParam & aInParam, nl::Weave::Binding::OutEventParam & aOutParam);
+};
+
+static MockWdmUpdateClientImpl gWdmUpdateClient;
+
+MockWdmUpdateClient * MockWdmUpdateClient::GetInstance ()
+{
+ return &gWdmUpdateClient;
+}
+
+MockWdmUpdateClientImpl::MockWdmUpdateClientImpl()
+ : mSinkCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID), mSinkCatalogStore, sizeof(mSinkCatalogStore) / sizeof(mSinkCatalogStore[0]))
+{
+ mSinkCatalog.AddAt(0, &mLocaleSettingsTraitDataSink, kLocaleSettingsSinkIndex);
+}
+
+WEAVE_ERROR MockWdmUpdateClientImpl::Init (nl::Weave::WeaveExchangeManager *aExchangeMgr,
+ const char * const aTestCaseId,
+ const int aTestSecurityMode,
+ const uint32_t aKeyId)
+{
+ mExchangeMgr = aExchangeMgr;
+ mBinding = NULL;
+ onCompleteTest = NULL;
+
+ if (NULL != aTestCaseId)
+ {
+ mTestCaseId = atoi(aTestCaseId);
+ }
+ else
+ {
+ mTestCaseId = 0;
+ }
+
+ mTestSecurityMode = aTestSecurityMode;
+ mKeyId = aKeyId;
+
+ WeaveLogDetail(DataManagement, "Test Case ID: %d", mTestCaseId);
+ WeaveLogDetail(DataManagement, "Security Mode: %d", mTestSecurityMode);
+ WeaveLogDetail(DataManagement, "Key ID: %d", aKeyId);
+
+ return WEAVE_NO_ERROR;
+}
+
+WEAVE_ERROR MockWdmUpdateClientImpl::StartTesting(const uint64_t aPublisherNodeId, const uint16_t aSubnetId)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ mPublisherNodeId = aPublisherNodeId;
+ mPublisherSubnetId = aSubnetId;
+
+ mBinding = mExchangeMgr->NewBinding(BindingEventCallback, this);
+ VerifyOrExit(NULL != mBinding, err = WEAVE_ERROR_NO_MEMORY);
+
+ if (mBinding->CanBePrepared())
+ {
+ err = mBinding->RequestPrepare();
+ SuccessOrExit(err);
+ }
+
+ mTraitPaths[0].mTraitDataHandle = kLocaleSettingsSinkIndex;
+ mTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle;
+
+exit:
+ WeaveLogFunctError(err);
+
+ if (err != WEAVE_NO_ERROR && mBinding != NULL)
+ {
+ mBinding->Release();
+ mBinding = NULL;
+ }
+ return err;
+}
+
+WEAVE_ERROR MockWdmUpdateClientImpl::AddArgumentCallback(UpdateClient * apClient, void * const aAppState, nl::Weave::TLV::TLVWriter &aOutWriter)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint32_t dummyUInt = 7;
+ bool dummyBool = false;
+ nl::Weave::TLV::TLVType dummyType = nl::Weave::TLV::kTLVType_NotSpecified;
+
+ err = aOutWriter.StartContainer(nl::Weave::TLV::ContextTag(UpdateRequest::kCsTag_Argument), nl::Weave::TLV::kTLVType_Structure, dummyType);
+ SuccessOrExit(err);
+
+ err = aOutWriter.Put(nl::Weave::TLV::ContextTag(1), dummyUInt);
+ SuccessOrExit(err);
+ err = aOutWriter.PutBoolean(nl::Weave::TLV::ContextTag(2), dummyBool);
+ SuccessOrExit(err);
+
+ err = aOutWriter.EndContainer(dummyType);
+ SuccessOrExit(err);
+
+exit:
+ WeaveLogFunctError(err);
+
+ return err;
+}
+
+WEAVE_ERROR MockWdmUpdateClientImpl::PrepareBinding()
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ Binding::Configuration bindingConfig = mBinding->BeginConfiguration()
+ .Target_NodeId(mPublisherNodeId) // TODO: aPublisherNodeId
+ .Transport_UDP_WRM()
+ .Transport_DefaultWRMPConfig(gWRMPConfig)
+
+ // (default) max num of msec between any outgoing message and next incoming message (could be a response to it)
+ .Exchange_ResponseTimeoutMsec(kResponseTimeoutMsec);
+
+ if (nl::Weave::kWeaveSubnetId_NotSpecified != mPublisherSubnetId)
+ {
+ bindingConfig.TargetAddress_WeaveFabric(mPublisherSubnetId);
+ }
+
+ switch (mTestSecurityMode)
+ {
+ case WeaveSecurityMode::kCASE:
+ WeaveLogDetail(DataManagement, "security mode is kWdmSecurity_CASE");
+ bindingConfig.Security_SharedCASESession();
+ break;
+
+ case WeaveSecurityMode::kGroupEnc:
+ WeaveLogDetail(DataManagement, "security mode is kWdmSecurity_GroupKey");
+ if (mKeyId == WeaveKeyId::kNone)
+ {
+ WeaveLogDetail(DataManagement, "Please specify a group encryption key id using the --group-enc-... options.\n");
+ err = WEAVE_ERROR_INVALID_KEY_ID;
+ SuccessOrExit(err);
+ }
+ bindingConfig.Security_Key(mKeyId);
+ //.Security_Key(0x5536);
+ //.Security_Key(0x4436);
+ break;
+
+ case WeaveSecurityMode::kNone:
+ WeaveLogDetail(DataManagement, "security mode is None");
+ bindingConfig.Security_None();
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, "security mode is not supported");
+ err = WEAVE_ERROR_UNSUPPORTED_AUTH_MODE;
+ SuccessOrExit(err);
+ }
+
+ err = bindingConfig.PrepareBinding();
+ SuccessOrExit(err);
+
+exit:
+ WeaveLogFunctError(err);
+ return err;
+}
+
+WEAVE_ERROR MockWdmUpdateClientImpl::SendUpdateRequest(void)
+{
+ mWdmUpdateHelper.Setup(mBinding, this, EventCallback);
+ mWdmUpdateHelper.UpdateAndSendLeaf();
+ mWdmUpdateHelper.TearDown();
+ return WEAVE_NO_ERROR;
+}
+
+void MockWdmUpdateClientImpl::BindingEventCallback (void * const apAppState, const nl::Weave::Binding::EventType aEvent,
+ const nl::Weave::Binding::InEventParam & aInParam, nl::Weave::Binding::OutEventParam & aOutParam)
+{
+
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogDetail(DataManagement, "%s: Event(%d)", __func__, aEvent);
+
+ MockWdmUpdateClientImpl * const initiator = reinterpret_cast<MockWdmUpdateClientImpl *>(apAppState);
+
+ switch (aEvent)
+ {
+ case nl::Weave::Binding::kEvent_PrepareRequested:
+ WeaveLogDetail(DataManagement, "kEvent_PrepareRequested");
+ err = initiator->PrepareBinding();
+ SuccessOrExit(err);
+ break;
+
+ case nl::Weave::Binding::kEvent_PrepareFailed:
+ err = aInParam.PrepareFailed.Reason;
+ WeaveLogDetail(DataManagement, "kEvent_PrepareFailed: reason");
+ break;
+
+ case nl::Weave::Binding::kEvent_BindingFailed:
+ err = aInParam.BindingFailed.Reason;
+ WeaveLogDetail(DataManagement, "kEvent_BindingFailed: reason");
+ break;
+
+ case nl::Weave::Binding::kEvent_BindingReady:
+ WeaveLogDetail(DataManagement, "kEvent_BindingReady");
+ err = initiator->SendUpdateRequest();
+ break;
+
+ case nl::Weave::Binding::kEvent_DefaultCheck:
+ WeaveLogDetail(DataManagement, "kEvent_DefaultCheck");
+
+ default:
+ nl::Weave::Binding::DefaultEventHandler(apAppState, aEvent, aInParam, aOutParam);
+ }
+
+exit:
+
+ if (err != WEAVE_NO_ERROR)
+ {
+ WeaveLogDetail(DataManagement, "error in BindingEventCallback");
+ initiator->mBinding->Release();
+ initiator->mBinding = NULL;
+ }
+
+ WeaveLogFunctError(err);
+}
+
+void MockWdmUpdateClientImpl::EventCallback (void * const aAppState, UpdateClient::EventType aEvent, const UpdateClient::InEventParam & aInParam, UpdateClient::OutEventParam & aOutParam)
+{
+ MockWdmUpdateClientImpl * const initiator = reinterpret_cast<MockWdmUpdateClientImpl *>(aAppState);
+
+ switch (aEvent)
+ {
+ case UpdateClient::kEvent_UpdateComplete:
+ WeaveLogDetail(DataManagement, "Client->kEvent_UpdateComplete");
+ if ((aInParam.UpdateComplete.Reason == WEAVE_NO_ERROR) && (nl::Weave::Profiles::Common::kStatus_Success == aInParam.UpdateComplete.StatusReportPtr->mStatusCode))
+ {
+ WeaveLogDetail(DataManagement, "Good Iteration, Update: path result: success");
+ }
+ else
+ {
+ WeaveLogDetail(DataManagement, "Update: path failed: %s",
+ ErrorStr(aInParam.UpdateComplete.Reason));
+ }
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, "Unknown UpdateClient event: %d", aEvent);
+ break;
+ }
+
+ initiator->onCompleteTest();
+}
+
+#endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
diff --git a/src/test-apps/MockWdmUpdateClient.h b/src/test-apps/MockWdmUpdateClient.h
new file mode 100644
index 0000000..1582c32
--- /dev/null
+++ b/src/test-apps/MockWdmUpdateClient.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * 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.
+ * 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.
+ */
+
+/**
+ * @file
+ * This file declares the Weave Data Management mock Update client.
+ *
+ */
+
+#ifndef MOCKWDMUPDATECLIENT_H_
+#define MOCKWDMUPDATECLIENT_H_
+
+#include <Weave/Core/WeaveExchangeMgr.h>
+
+class MockWdmUpdateClient
+{
+public:
+ static MockWdmUpdateClient * GetInstance ();
+
+ virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, const char * const aTestCaseId, const int aTestSecurityMode, const uint32_t aKeyId) = 0;
+
+ virtual WEAVE_ERROR StartTesting(const uint64_t aPublisherNodeId, const uint16_t aSubnetId) = 0;
+
+ typedef void(*HandleCompleteTestFunct)();
+
+ HandleCompleteTestFunct onCompleteTest;
+};
+
+#endif /* MOCKWDMUPDATECLIENT_H_ */
diff --git a/src/test-apps/MockWdmUpdateServer.cpp b/src/test-apps/MockWdmUpdateServer.cpp
new file mode 100644
index 0000000..d23f95d
--- /dev/null
+++ b/src/test-apps/MockWdmUpdateServer.cpp
@@ -0,0 +1,154 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * 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.
+ * 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.
+ */
+
+/**
+ * @file
+ * This file implements the Weave Data Management mock Update server.
+ *
+ */
+
+#define WEAVE_CONFIG_ENABLE_LOG_FILE_LINE_FUNC_ON_ERROR 1
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif // __STDC_FORMAT_MACROS
+
+#include <Weave/Core/WeaveError.h>
+#include <Weave/Core/WeaveSecurityMgr.h>
+#include <Weave/Support/CodeUtils.h>
+#include <Weave/Core/WeaveTLVDebug.hpp>
+#include "MockWdmUpdateServer.h"
+#include <Weave/Profiles/WeaveProfiles.h>
+#include <Weave/Profiles/data-management/DataManagement.h>
+#include "MockSinkTraits.h"
+#include "MockSourceTraits.h"
+#include "TestGroupKeyStore.h"
+
+using nl::Weave::System::PacketBuffer;
+
+#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
+
+using namespace nl::Weave::Profiles::DataManagement;
+
+/**
+ * Log the specified message in the form of @a aFormat.
+ *
+ * @param[in] aFormat A pointer to a NULL-terminated C string with
+ * C Standard Library-style format specifiers
+ * containing the log message to be formatted and
+ * logged.
+ * @param[in] ... An argument list whose elements should correspond
+ * to the format specifiers in @a aFormat.
+ *
+ */
+static void TLVPrettyPrinter(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+
+ // There is no proper Weave logging routine for us to use here
+ vprintf(aFormat, args);
+
+ va_end(args);
+}
+
+static WEAVE_ERROR DebugPrettyPrint(nl::Weave::TLV::TLVReader & aReader)
+{
+ return nl::Weave::TLV::Debug::Dump(aReader, TLVPrettyPrinter);
+}
+
+class MockWdmUpdateServerImpl: public MockWdmUpdateServer
+{
+public:
+
+ virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, const char * const aTestCaseId)
+ {
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogDetail(DataManagement, "Test Case ID: %s", aTestCaseId);
+
+ err = aExchangeMgr->RegisterUnsolicitedMessageHandler(nl::Weave::Profiles::kWeaveProfile_WDM, kMsgType_UpdateRequest, IncomingUpdateRequest, this);
+ SuccessOrExit(err);
+
+ exit:
+ return err;
+ }
+
+private:
+
+ static void IncomingUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
+ const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
+ uint8_t msgType, PacketBuffer *payload);
+};
+
+static MockWdmUpdateServerImpl gWdmUpdateServer;
+
+MockWdmUpdateServer * MockWdmUpdateServer::GetInstance ()
+{
+ return &gWdmUpdateServer;
+}
+
+void MockWdmUpdateServerImpl::IncomingUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
+ const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
+ uint8_t msgType, PacketBuffer *payload)
+{
+ // TODO: 1. Add Parse to check incoming update request. 2. Add statusList and version list in status report
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ WeaveLogDetail(DataManagement, "Incoming Update Request");
+
+ nl::Weave::TLV::TLVReader reader;
+ uint8_t statusReportLen = 6;
+ uint8_t * p;
+ reader.Init(payload);
+ DebugPrettyPrint(reader);
+
+ PacketBuffer * msgBuf = PacketBuffer::NewWithAvailableSize(statusReportLen);
+ VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY);
+
+ p = msgBuf->Start();
+ nl::Weave::Encoding::LittleEndian::Write32(p, nl::Weave::Profiles::kWeaveProfile_Common);
+ nl::Weave::Encoding::LittleEndian::Write16(p, nl::Weave::Profiles::Common::kStatus_Success);
+ msgBuf->SetDataLength(statusReportLen);
+
+ err = ec->SendMessage(nl::Weave::Profiles::kWeaveProfile_Common, nl::Weave::Profiles::Common::kMsgType_StatusReport, msgBuf, nl::Weave::ExchangeContext::kSendFlag_RequestAck);
+ msgBuf = NULL;
+ SuccessOrExit(err);
+
+exit:
+ WeaveLogFunctError(err);
+
+ if (NULL != payload)
+ {
+ PacketBuffer::Free(payload);
+ payload = NULL;
+ }
+
+ if (NULL != msgBuf)
+ {
+ PacketBuffer::Free(msgBuf);
+ msgBuf = NULL;
+ }
+
+ if (NULL != ec)
+ {
+ ec->Close();
+ }
+}
+
+#endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
diff --git a/src/test-apps/MockWdmUpdateServer.h b/src/test-apps/MockWdmUpdateServer.h
new file mode 100644
index 0000000..3736bb7
--- /dev/null
+++ b/src/test-apps/MockWdmUpdateServer.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2019 Google LLC.
+ * 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.
+ * 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.
+ */
+
+/**
+ * @file
+ * This file declares the Weave Data Management mock Update server.
+ *
+ */
+
+#ifndef MOCKWDMUPDATESERVER_H_
+#define MOCKWDMUPDATESERVER_H_
+
+#include <Weave/Core/WeaveExchangeMgr.h>
+
+class MockWdmUpdateServer
+{
+public:
+ static MockWdmUpdateServer * GetInstance ();
+
+ virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, const char * const aTestCaseId) = 0;
+};
+
+
+#endif /* MOCKWDMUPDATESERVER_H_ */
diff --git a/src/test-apps/TestWdmNext.cpp b/src/test-apps/TestWdmNext.cpp
index 8646e6e..9fc5118 100644
--- a/src/test-apps/TestWdmNext.cpp
+++ b/src/test-apps/TestWdmNext.cpp
@@ -1,6 +1,7 @@
/*
*
- * Copyright (c) 2016-2017 Nest Labs, Inc.
+ * Copyright (c) 2016-2018 Nest Labs, Inc.
+ * Copyright (c) 2019 Google LLC.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -51,6 +52,8 @@
#include "MockWdmSubscriptionInitiator.h"
#include "MockWdmSubscriptionResponder.h"
+#include "MockWdmUpdateClient.h"
+#include "MockWdmUpdateServer.h"
#include "MockWdmViewClient.h"
#include "MockWdmViewServer.h"
#include "WdmNextPerfUtility.h"
@@ -189,9 +192,29 @@
err = MockWdmViewServer::GetInstance()->Init(&ExchangeMgr, gMockWdmNodeOptions.mTestCaseId);
FAIL_ERROR(err, "MockWdmViewServer.Init failed");
break;
-
#endif // ENABLE_VIEW_TEST
+ case kToolOpt_WdmSimpleUpdateClient:
+ if (gMockWdmNodeOptions.mWdmPublisherNodeId != kAnyNodeId)
+ {
+ err = MockWdmUpdateClient::GetInstance()->Init(&ExchangeMgr, 0, gWeaveSecurityMode.SecurityMode, gGroupKeyEncOptions.GetEncKeyId());
+ FAIL_ERROR(err, "MockWdmUpdateClient.Init failed");
+ err = MockWdmUpdateClient::GetInstance()->StartTesting(gMockWdmNodeOptions.mWdmPublisherNodeId, gMockWdmNodeOptions.mWdmUseSubnetId);
+ FAIL_ERROR(err, "MockWdmUpdateClient.StartTesting failed");
+
+ MockWdmUpdateClient::GetInstance()-> onCompleteTest = HandleWdmCompleteTest;
+ }
+ else
+ {
+ err = WEAVE_ERROR_INVALID_ARGUMENT;
+ FAIL_ERROR(err, "Simple Update Client requires node ID to some publisher");
+ }
+ break;
+ case kToolOpt_WdmSimpleUpdateServer:
+ err = MockWdmUpdateServer::GetInstance()->Init(&ExchangeMgr, 0);
+ FAIL_ERROR(err, "MockWdmUpdateServer.Init failed");
+ break;
+
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmSimpleSublessNotifyClient:
err = TestWdmSubscriptionlessNotificationReceiver::GetInstance()->Init(&ExchangeMgr);
diff --git a/src/test-apps/happy/test-templates/WeaveWdmNext.py b/src/test-apps/happy/test-templates/WeaveWdmNext.py
index 24a0d02..5a104e3 100644
--- a/src/test-apps/happy/test-templates/WeaveWdmNext.py
+++ b/src/test-apps/happy/test-templates/WeaveWdmNext.py
@@ -377,6 +377,11 @@
smoke_check = True
else:
smoke_check = False
+ elif self.wdm_option == "update":
+ if any("kEvent_UpdateComplete" in s for s in kevents):
+ smoke_check = True
+ else:
+ smoke_check = False
result["smoke_check"] = smoke_check
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_standalone_update_01.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_standalone_update_01.py
new file mode 100755
index 0000000..9585979
--- /dev/null
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_standalone_update_01.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+
+#
+# Copyright (c) 2019 Google LLC.
+# 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.
+# 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.
+#
+
+#
+# @file
+# Calls Weave WDM Update between nodes.
+# WDM Stanadlone Update 01: Client send update request to publisher, and receive status report
+#
+
+import unittest
+import set_test_path
+from weave_wdm_next_test_base import weave_wdm_next_test_base
+import WeaveUtilities
+
+
+class test_weave_wdm_next_update_01(weave_wdm_next_test_base):
+
+ def test_weave_wdm_next_mutual_subscribe_01(self):
+ wdm_next_args = {}
+
+ wdm_next_args['wdm_option'] = "update"
+ wdm_next_args['total_client_count'] = 0
+ wdm_next_args['final_client_status'] = 0
+ wdm_next_args['timer_client_period'] = 0
+ wdm_next_args['test_client_iterations'] = 1
+
+ wdm_next_args['total_server_count'] = 0
+
+ wdm_next_args['client_log_check'] = []
+ wdm_next_args['server_log_check'] = []
+
+ wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
+ wdm_next_args['test_case_name'] = ['WDM Standalone Update 01: Client send update request to publisher, and receive status report',
+ ]
+ print 'test file: ' + self.__class__.__name__
+ print "weave-wdm-next test WDM Stanadlone Update 01"
+ super(test_weave_wdm_next_update_01, self).weave_wdm_next_test_base(wdm_next_args)
+
+
+if __name__ == "__main__":
+ WeaveUtilities.run_unittest()
\ No newline at end of file
diff --git a/src/test-apps/mock-device.cpp b/src/test-apps/mock-device.cpp
index 7c8b981..12601f1 100644
--- a/src/test-apps/mock-device.cpp
+++ b/src/test-apps/mock-device.cpp
@@ -63,6 +63,8 @@
#include "MockDCServer.h"
#include "MockOpActions.h"
#include "MockTokenPairingServer.h"
+#include "MockWdmUpdateClient.h"
+#include "MockWdmUpdateServer.h"
#include "MockWdmViewClient.h"
#include "MockWdmViewServer.h"
@@ -221,7 +223,6 @@
kToolOpt_TimeSyncModeServiceOverTunnel = 1042, // specify that the Time Client Sync mode is Service (time sync with Service over a tunnel)
kToolOpt_UseServiceDir,
kToolOpt_SuppressAccessControl,
-
// only for weave over bluez peripheral
#if CONFIG_BLE_PLATFORM_BLUEZ
kToolOpt_EnableWeaveBluezPeripheral,
@@ -392,6 +393,12 @@
" --wdm-simple-view-server\n"
" Initiate a simple WDM Next view server\n"
"\n"
+ " --wdm-simple-update-client\n"
+ " Initiate a simple WDM Next update client\n"
+ "\n"
+ " --wdm-simple-update-server\n"
+ " Initiate a simple WDM Next update server\n"
+ "\n"
" --wdm-one-way-sub-client\n"
" Initiate a subscription to some WDM Next publisher\n"
"\n"