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"