| /* |
| * |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * 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 unit tests for the Weave TLV implementation. |
| * |
| */ |
| |
| #include "ToolCommon.h" |
| |
| #include <nlbyteorder.h> |
| #include <nltest.h> |
| |
| #include <Weave/Core/WeaveCore.h> |
| #include <Weave/Core/WeaveTLV.h> |
| #include <Weave/Core/WeaveTLVDebug.hpp> |
| #include <Weave/Core/WeaveTLVUtilities.hpp> |
| #include <Weave/Core/WeaveTLVData.hpp> |
| #include <Weave/Core/WeaveCircularTLVBuffer.h> |
| #include <Weave/Support/RandUtils.h> |
| |
| #include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h> |
| #include <Weave/Profiles/data-management/DataManagement.h> |
| |
| #include <nest/test/trait/TestHTrait.h> |
| #include <nest/test/trait/StructHStructSchema.h> |
| #include <nest/test/trait/StructDictionaryStructSchema.h> |
| |
| #include <nest/test/trait/TestCTrait.h> |
| #include <nest/test/trait/TestMismatchedCTrait.h> |
| |
| #include "MockMismatchedSchemaSinkAndSource.h" |
| |
| #include "MockTestBTrait.h" |
| |
| #include "TestPlatformTime.h" |
| |
| #include <new> |
| #include <map> |
| #include <set> |
| #include <algorithm> |
| #include <set> |
| #include <string> |
| #include <iterator> |
| |
| #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
| #include <lwip/init.h> |
| #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
| |
| using namespace nl; |
| using namespace nl::Weave::TLV; |
| using namespace nl::Weave::Profiles::DataManagement; |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // System/Platform definitions |
| // |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| namespace Private { |
| |
| static WEAVE_ERROR SetSystemTime(const nl::Weave::Profiles::Time::timesync_t timestamp_usec) |
| { |
| return WEAVE_NO_ERROR; |
| } |
| |
| static WEAVE_ERROR GetSystemTimeMs(nl::Weave::Profiles::Time::timesync_t *p_timestamp_msec) |
| { |
| return WEAVE_NO_ERROR; |
| } |
| |
| } // namespace Private |
| |
| |
| namespace nl { |
| namespace Weave { |
| namespace Profiles { |
| namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) { |
| namespace Platform { |
| // for unit tests, the dummy critical section is sufficient. |
| void CriticalSectionEnter() |
| { |
| return; |
| } |
| |
| void CriticalSectionExit() |
| { |
| return; |
| } |
| } // Platform |
| } // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) |
| } |
| } |
| } |
| |
| static SubscriptionEngine *gSubscriptionEngine; |
| |
| SubscriptionEngine * SubscriptionEngine::GetInstance() |
| { |
| return gSubscriptionEngine; |
| } |
| |
| static void CheckDataSourceEmptySchema(nlTestSuite *inSuite, void *inContext); |
| static void CheckDataSinkEmptySchema(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmStatic_SingleLeafHandle(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_SingleLevelMerge(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_SingleLevelMergeDeep(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_DirtyStruct(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_DirtyLeafUnevenDepth(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_MergeHandleSetOverflow(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_MarkLeafHandleDirtyTwice(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmStatic_TestNullableLeaf(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_TestNullableStruct(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_TestNonNullableLeaf(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmStatic_TestEphemeralLeaf(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmStatic_TestEphemeralStruct(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmMismatched_PathInDataElement(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmMismatched_TopLevelPOD(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmMismatched_NestedStruct(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmMismatched_TopLevelStruct(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmMismatched_SetLeafDataMismatch(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmDictionary_DictionaryEntryAddition(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DictionaryEntriesAddition(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_ReplaceDictionary(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmDictionary_DeleteSingle(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteMultiple(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteHandleSetOverflow(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_AddDeleteDifferent(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteAndMarkDirty(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_MarkDirtyAndDelete(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteAndMarkFarDirty(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_AddAndDeleteSimilar(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_ModifyAndDeleteSimilar(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteAndModifySimilar(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteAndModifyLeafSimilar(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteStoreOverflowAndItemAddition(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DirtyStoreOverflowAndItemDeletion(nlTestSuite *inSuite, void *inContext); |
| static void TestTdmDictionary_DeleteEntryTwice(nlTestSuite *inSuite, void *inContext); |
| |
| static void TestTdmStatic_MultiInstance(nlTestSuite *inSuite, void *inContext); |
| |
| // Test Suite |
| |
| /** |
| * Test Suite that lists all the test functions. |
| */ |
| static const nlTest sTests[] = { |
| NL_TEST_DEF("Test TraitDataSource + schema with no properties", CheckDataSourceEmptySchema), |
| NL_TEST_DEF("Test TraitDataSink + schema with no properties", CheckDataSinkEmptySchema), |
| |
| // Tests the static schema portions of TDM |
| NL_TEST_DEF("Test Tdm (Static schema): Single leaf handle", TestTdmStatic_SingleLeafHandle), |
| |
| NL_TEST_DEF("Test Tdm (Static schema): Single level merge of two leaf handles", TestTdmStatic_SingleLevelMerge), |
| NL_TEST_DEF("Test Tdm (Static schema): Single level merge of two deeper leaf handles", TestTdmStatic_SingleLevelMergeDeep), |
| NL_TEST_DEF("Test Tdm (Static schema): Dirty structure node containing leaf handles", TestTdmStatic_DirtyStruct), |
| NL_TEST_DEF("Test Tdm (Static schema): Two dirty leaf handles at different depths", TestTdmStatic_DirtyLeafUnevenDepth), |
| NL_TEST_DEF("Test Tdm (Static schema): Overflow of merge handles", TestTdmStatic_MergeHandleSetOverflow), |
| NL_TEST_DEF("Test Tdm (Static schema): Mark same handle dirty twice", TestTdmStatic_MarkLeafHandleDirtyTwice), |
| |
| NL_TEST_DEF("Test Tdm (Static schema): Nullable leaf data", TestTdmStatic_TestNullableLeaf), |
| NL_TEST_DEF("Test Tdm (Static schema): Nullable struct", TestTdmStatic_TestNullableStruct), |
| NL_TEST_DEF("Test Tdm (Static schema): Non-Nullable leaf data", TestTdmStatic_TestNonNullableLeaf), |
| |
| NL_TEST_DEF("Test Tdm (Static schema): Ephemeral leaf data", TestTdmStatic_TestEphemeralLeaf), |
| NL_TEST_DEF("Test Tdm (Static schema): Ephemeral struct", TestTdmStatic_TestEphemeralStruct), |
| |
| // Tests a mismatched schema on publisher and subscriber |
| NL_TEST_DEF("Test Tdm (Mismatched schema): Path in DataElement is unmappable", TestTdmMismatched_PathInDataElement), |
| NL_TEST_DEF("Test Tdm (Mismatched schema): Schema extended by top level POD", TestTdmMismatched_TopLevelPOD), |
| NL_TEST_DEF("Test Tdm (Mismatched schema): Schema extended by nested struct", TestTdmMismatched_NestedStruct), |
| NL_TEST_DEF("Test Tdm (Mismatched schema): Schema extended by top level struct", TestTdmMismatched_TopLevelStruct), |
| NL_TEST_DEF("Test Tdm (Mismatched schema): App code doesn't match schema", TestTdmMismatched_SetLeafDataMismatch), |
| |
| // Tests the dictionary addition/modification portions of TDM |
| NL_TEST_DEF("Test Tdm (Dictionary Addition/Modification): Addition of single dictionary entries", TestTdmDictionary_DictionaryEntryAddition), |
| NL_TEST_DEF("Test Tdm (Dictionary Addition/Modification): Addition of two dictionary entries", TestTdmDictionary_DictionaryEntriesAddition), |
| NL_TEST_DEF("Test Tdm (Dictionary Addition/Modification): Replace dictionary", TestTdmDictionary_ReplaceDictionary), |
| |
| // Tests the dictionary deletion portions of TDM |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete single dictionary entry", TestTdmDictionary_DeleteSingle), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete two dictionary entries", TestTdmDictionary_DeleteMultiple), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Overflow of delete handle set", TestTdmDictionary_DeleteHandleSetOverflow), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Addition of one entry, deletion of another (within same dictionary)", TestTdmDictionary_AddDeleteDifferent), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete dictionary entry, then mark dictionary dirty", TestTdmDictionary_DeleteAndMarkDirty), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Mark dictionary dirty, then delete dictionary entry", TestTdmDictionary_MarkDirtyAndDelete), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete entry, then mark another node that is not in a dictionary in the tree as dirty", TestTdmDictionary_DeleteAndMarkFarDirty), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Add entry, then delete same entry", TestTdmDictionary_AddAndDeleteSimilar), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Modify entry, then delete same entry", TestTdmDictionary_ModifyAndDeleteSimilar), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete entry then add it back", TestTdmDictionary_DeleteAndModifySimilar), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Delete entry then add it back but only mark leaf of dictionary entry dirty", TestTdmDictionary_DeleteAndModifyLeafSimilar), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Test delete store overflow + item addition", TestTdmDictionary_DeleteStoreOverflowAndItemAddition), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Test dirty store overflow + item deletion", TestTdmDictionary_DirtyStoreOverflowAndItemDeletion), |
| NL_TEST_DEF("Test Tdm (Dictionary Deletion): Test delete same dictionary entry twice", TestTdmDictionary_DeleteEntryTwice), |
| |
| NL_TEST_DEF("Test Tdm (Multi Instance): Multi Instance", TestTdmStatic_MultiInstance), |
| |
| NL_TEST_SENTINEL() |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // Testing Empty Schema |
| // |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| const TraitSchemaEngine::PropertyInfo gEmptyPropertyMap[] = { |
| }; |
| |
| const TraitSchemaEngine gEmptyTraitSchema = { |
| { |
| 0x0, |
| gEmptyPropertyMap, |
| sizeof(gEmptyPropertyMap) / sizeof(gEmptyPropertyMap[0]), |
| 1, |
| #if (TDM_EXTENSION_SUPPORT) || (TDM_VERSIONING_SUPPORT) |
| 2, |
| #endif |
| #if (TDM_DICTIONARY_SUPPORT) |
| NULL, |
| #endif |
| NULL, |
| NULL, |
| NULL, |
| NULL, |
| #if (TDM_EXTENSION_SUPPORT) |
| NULL, |
| #endif |
| #if (TDM_VERSIONING_SUPPORT) |
| NULL, |
| #endif |
| } |
| }; |
| |
| class TestEmptyDataSource : public TraitDataSource { |
| public: |
| TestEmptyDataSource(const TraitSchemaEngine *aSchema) : TraitDataSource(aSchema), mGetLeafDataCalled(false) { } |
| |
| // Throw an error if this ever gets called. |
| WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter) { mGetLeafDataCalled = true; return WEAVE_ERROR_INVALID_ARGUMENT; } |
| |
| bool mGetLeafDataCalled; |
| }; |
| |
| class TestEmptyDataSink : public TraitDataSink { |
| public: |
| TestEmptyDataSink(const TraitSchemaEngine *aSchema); |
| |
| WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader) { mSetLeafDataCalled = true; return WEAVE_ERROR_INVALID_ARGUMENT; } |
| WEAVE_ERROR OnEvent(uint16_t aType, void *aInEventParam); |
| |
| bool mSetLeafDataCalled; |
| bool mEventDataElementBeginSignalled; |
| bool mEventDataElementEndSignalled; |
| }; |
| |
| TestEmptyDataSink::TestEmptyDataSink(const TraitSchemaEngine *aSchema) |
| : TraitDataSink(aSchema) |
| { |
| mSetLeafDataCalled = false; |
| mEventDataElementBeginSignalled = false; |
| mEventDataElementEndSignalled = false; |
| } |
| |
| WEAVE_ERROR TestEmptyDataSink::OnEvent(uint16_t aType, void *aInEventParam) |
| { |
| if (aType == kEventDataElementBegin) { |
| mEventDataElementBeginSignalled = true; |
| } |
| else if (aType == kEventDataElementEnd) { |
| mEventDataElementEndSignalled = true; |
| } |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| static void CheckDataSourceEmptySchema(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| TLVWriter writer; |
| TLVType dummyContainerType; |
| uint8_t buf[1024]; |
| TestEmptyDataSource dataSource(&gEmptyTraitSchema); |
| DataElement::Parser parser; |
| TLVReader reader; |
| |
| static const uint8_t Encoding[] = |
| { |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_ANONYMOUS), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(ContextTag(DataElement::kCsTag_Data))), |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| }; |
| |
| writer.Init(buf, sizeof(buf)); |
| |
| err = writer.StartContainer(AnonymousTag, kTLVType_Structure, dummyContainerType); |
| SuccessOrExit(err); |
| |
| err = dataSource.ReadData(kRootPropertyPathHandle, ContextTag(DataElement::kCsTag_Data), writer); |
| SuccessOrExit(err); |
| |
| // The 'GetLeafData' method shouldn't get called on the source given there is no properties in this trait. |
| NL_TEST_ASSERT(inSuite, dataSource.mGetLeafDataCalled == false); |
| |
| err = writer.EndContainer(dummyContainerType); |
| SuccessOrExit(err); |
| |
| err = writer.Finalize(); |
| reader.Init(buf, writer.GetLengthWritten()); |
| |
| NL_TEST_ASSERT(inSuite, memcmp(Encoding, buf, sizeof(Encoding)) == 0); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| return; |
| } |
| |
| static void CheckDataSinkEmptySchema(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| TestEmptyDataSink dataSink(&gEmptyTraitSchema); |
| TLVReader reader; |
| |
| static const uint8_t Encoding[] = |
| { |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_ANONYMOUS), |
| nlWeaveTLV_UINT64(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(ContextTag(DataElement::kCsTag_Version)), 1), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(ContextTag(DataElement::kCsTag_Data))), |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| }; |
| |
| reader.Init(Encoding, sizeof(Encoding)); |
| |
| err = reader.Next(); |
| SuccessOrExit(err); |
| |
| err = dataSink.StoreDataElement(kRootPropertyPathHandle, reader, 0, NULL, NULL); |
| SuccessOrExit(err); |
| |
| // The 'SetLeafData' method on the datasink shouldn't get called since there are no properties in this trait. |
| // Additionally, we should still receive events indicating data element begin/end. |
| NL_TEST_ASSERT(inSuite, dataSink.mSetLeafDataCalled == false); |
| NL_TEST_ASSERT(inSuite, dataSink.mEventDataElementBeginSignalled == true); |
| NL_TEST_ASSERT(inSuite, dataSink.mEventDataElementEndSignalled == true); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // Testing NotificationEngine + TraitData |
| // |
| /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| namespace nl { |
| namespace Weave { |
| namespace Profiles { |
| namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) { |
| |
| using namespace Schema::Nest::Test::Trait; |
| |
| // |
| // This is a source that publishes values for the test_h_trait. This includes providing values for two separate dictionaries |
| // as well as values for the rest of the fields in the static part of the schema. I designed the test_h_trait to specifically |
| // have all the fields be of the same type (i.e uint32_t) to focus the testing not on the value types, but rather validating the |
| // fields extracted by the Notification Engine. |
| // |
| class TestTdmSource : public TraitDataSource { |
| public: |
| TestTdmSource(); |
| void SetValue(PropertyPathHandle aPropertyPathHandle, uint32_t aValue); |
| void Reset(); |
| |
| private: |
| WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter); |
| WEAVE_ERROR GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey); |
| |
| public: |
| std::map <PropertyPathHandle, uint32_t> mValues; |
| std::map <uint16_t, StructDictionary> mDictlValues; |
| std::map <uint16_t, StructDictionary> mDictSaValues; |
| |
| uint32_t mBackingValue; |
| }; |
| |
| TestTdmSource::TestTdmSource() |
| : TraitDataSource(&TestHTrait::TraitSchema) |
| { |
| mBackingValue = 1; |
| } |
| |
| void TestTdmSource::SetValue(PropertyPathHandle aPropertyPathHandle, uint32_t aValue) |
| { |
| mValues[aPropertyPathHandle] = aValue; |
| SetDirty(aPropertyPathHandle); |
| } |
| |
| void TestTdmSource::Reset() |
| { |
| mValues.clear(); |
| mDictlValues.clear(); |
| mDictSaValues.clear(); |
| mBackingValue = 1; |
| } |
| |
| WEAVE_ERROR TestTdmSource::GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey) |
| { |
| static std::map<uint16_t, StructDictionary>::iterator it; |
| std::map <uint16_t, StructDictionary> *mapPtr = (aDictionaryHandle == TestHTrait::kPropertyHandle_L) ? &mDictlValues : &mDictSaValues; |
| |
| if (aContext == 0) { |
| it = mapPtr->begin(); |
| } |
| else { |
| it++; |
| } |
| |
| aContext = (uintptr_t)⁢ |
| if (it == mapPtr->end()) { |
| return WEAVE_END_OF_INPUT; |
| } |
| else { |
| aKey = it->first; |
| } |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR TestTdmSource::GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| PropertyPathHandle dictionaryItemHandle = kNullPropertyPathHandle; |
| |
| if (GetSchemaEngine()->IsInDictionary(aLeafHandle, dictionaryItemHandle)) { |
| PropertyPathHandle dictionaryHandle = GetSchemaEngine()->GetParent(dictionaryItemHandle); |
| PropertyDictionaryKey key = GetPropertyDictionaryKey(dictionaryItemHandle); |
| |
| if (dictionaryHandle == TestHTrait::kPropertyHandle_L) { |
| if (mDictlValues.find(key) != mDictlValues.end()) { |
| StructDictionary item = mDictlValues[key]; |
| uint32_t val; |
| |
| switch (GetPropertySchemaHandle(aLeafHandle)) { |
| case TestHTrait::kPropertyHandle_L_Value_Da: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> l[%u].da = %u", key, item.da); |
| val = item.da; |
| break; |
| |
| case TestHTrait::kPropertyHandle_L_Value_Db: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> l[%u].db = %u", key, item.da); |
| val = item.db; |
| break; |
| |
| case TestHTrait::kPropertyHandle_L_Value_Dc: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> l[%u].dc = %u", key, item.da); |
| val = item.dc; |
| break; |
| |
| default: |
| WeaveLogError(DataManagement, "Unknown handle passed in!"); |
| return WEAVE_ERROR_INVALID_ARGUMENT; |
| break; |
| } |
| |
| err = aWriter.Put(aTagToWrite, val); |
| SuccessOrExit(err); |
| } |
| else { |
| WeaveLogError(DataManagement, "Requested key %u for dictionary handle %u that doesn't exist!", key, dictionaryHandle); |
| return WEAVE_ERROR_INVALID_ARGUMENT; |
| } |
| } |
| |
| if (dictionaryHandle == TestHTrait::kPropertyHandle_K_Sa) { |
| if (mDictSaValues.find(key) != mDictSaValues.end()) { |
| StructDictionary item = mDictSaValues[key]; |
| uint32_t val; |
| |
| switch (GetPropertySchemaHandle(aLeafHandle)) { |
| case TestHTrait::kPropertyHandle_K_Sa_Value_Da: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> k.sa[%u].da = %u", key, item.da); |
| val = item.da; |
| break; |
| |
| case TestHTrait::kPropertyHandle_K_Sa_Value_Db: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> k.sa[%u].db = %u", key, item.db); |
| val = item.db; |
| break; |
| |
| case TestHTrait::kPropertyHandle_K_Sa_Value_Dc: |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> k.sa[%u].dc = %u", key, item.dc); |
| val = item.dc; |
| break; |
| |
| default: |
| WeaveLogError(DataManagement, "Unknown handle passed in!"); |
| return WEAVE_ERROR_INVALID_ARGUMENT; |
| break; |
| } |
| |
| err = aWriter.Put(aTagToWrite, val); |
| SuccessOrExit(err); |
| } |
| else { |
| WeaveLogError(DataManagement, "Requested key %u for dictionary handle %u that doesn't exist!", key, dictionaryHandle); |
| return WEAVE_ERROR_INVALID_ARGUMENT; |
| } |
| } |
| } |
| else { |
| if (mValues.find(aLeafHandle) != mValues.end()) { |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> handle:%u = %u", aLeafHandle, mValues[aLeafHandle]); |
| err = aWriter.Put(aTagToWrite, mValues[aLeafHandle]); |
| SuccessOrExit(err); |
| } |
| else { |
| WeaveLogDetail(DataManagement, "[TestTdmSource::GetLeafData] >> *handle:%u = %u", aLeafHandle, mBackingValue); |
| err = aWriter.Put(aTagToWrite, mBackingValue); |
| } |
| } |
| |
| exit: |
| return err; |
| } |
| |
| // |
| // This is a very special sink that tracks all the replaces, deletions and modifications that are sent to it through the |
| // OnEvent and SetLeafData calls. This then allows for programmatic validation of the specific set of data that is expected for a set of modifications |
| // that are made on the source side. |
| // |
| class TestTdmSink : public TraitDataSink { |
| public: |
| TestTdmSink(); |
| void Reset(); |
| void DumpChangeSets(); |
| |
| bool ValidateChangeSets(std::map <PropertyPathHandle, uint32_t> aTargetModifiedSet, std::set <PropertyPathHandle> aTargetDeletedSet, std::set <PropertyPathHandle> aTargetReplacedSet); |
| |
| private: |
| WEAVE_ERROR OnEvent(uint16_t aType, void *aInParam); |
| WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader); |
| |
| std::map <PropertyPathHandle, uint32_t> mModifiedHandles; |
| std::set <PropertyPathHandle> mDeletedHandles; |
| std::set <PropertyPathHandle> mReplacedDictionaries; |
| }; |
| |
| TestTdmSink::TestTdmSink() |
| : TraitDataSink(&TestHTrait::TraitSchema) |
| { |
| } |
| |
| void TestTdmSink::Reset() |
| { |
| mModifiedHandles.clear(); |
| mDeletedHandles.clear(); |
| mReplacedDictionaries.clear(); |
| ClearVersion(); |
| } |
| |
| void TestTdmSink::DumpChangeSets() |
| { |
| for (std::map <PropertyPathHandle, uint32_t>::iterator map_it = mModifiedHandles.begin(); map_it != mModifiedHandles.end(); ++map_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::DumpChangeSets] <Modified> %u:%u = %u", GetPropertyDictionaryKey(map_it->first), GetPropertySchemaHandle(map_it->first), map_it->second); |
| } |
| |
| for (std::set <PropertyPathHandle>::iterator set_it = mDeletedHandles.begin(); set_it != mDeletedHandles.end(); ++set_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::DumpChangeSets] <Deleted> %u:%u", GetPropertyDictionaryKey(*set_it), GetPropertySchemaHandle(*set_it)); |
| } |
| |
| for (std::set <PropertyPathHandle>::iterator set_it = mReplacedDictionaries.begin(); set_it != mReplacedDictionaries.end(); ++set_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::DumpChangeSets] <Replaced> %u:%u", GetPropertyDictionaryKey(*set_it), GetPropertySchemaHandle(*set_it)); |
| } |
| } |
| |
| bool TestTdmSink::ValidateChangeSets(std::map <PropertyPathHandle, uint32_t> aTargetModifiedSet, std::set <PropertyPathHandle> aTargetDeletedSet, std::set <PropertyPathHandle> aTargetReplacedSet) |
| { |
| std::map <PropertyPathHandle, uint32_t> modifiedDiff; |
| std::set <PropertyPathHandle> deletedDiff; |
| std::set <PropertyPathHandle> replacedDiff; |
| bool match = true; |
| |
| std::set_symmetric_difference(mModifiedHandles.begin(), mModifiedHandles.end(), aTargetModifiedSet.begin(), aTargetModifiedSet.end(), inserter(modifiedDiff, modifiedDiff.begin())); |
| std::set_symmetric_difference(mDeletedHandles.begin(), mDeletedHandles.end(), aTargetDeletedSet.begin(), aTargetDeletedSet.end(), inserter(deletedDiff, deletedDiff.begin())); |
| std::set_symmetric_difference(mReplacedDictionaries.begin(), mReplacedDictionaries.end(), aTargetReplacedSet.begin(), aTargetReplacedSet.end(), inserter(replacedDiff, replacedDiff.begin())); |
| |
| for (std::map <PropertyPathHandle, uint32_t>::iterator map_it = modifiedDiff.begin(); map_it != modifiedDiff.end(); ++map_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::ValidateChangeSets] <delta modified> %u:%u = %u", GetPropertyDictionaryKey(map_it->first), GetPropertySchemaHandle(map_it->first), map_it->second); |
| match = false; |
| } |
| |
| for (std::set <PropertyPathHandle>::iterator set_it = deletedDiff.begin(); set_it != deletedDiff.end(); ++set_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::ValidateChangeSets] <delta deleted> %u:%u", GetPropertyDictionaryKey(*set_it), GetPropertySchemaHandle(*set_it)); |
| match = false; |
| } |
| |
| for (std::set <PropertyPathHandle>::iterator set_it = replacedDiff.begin(); set_it != replacedDiff.end(); ++set_it) { |
| WeaveLogDetail(DataManagement, "[TestTdmSink::ValidateChangeSets] <delta replaced> %u:%u", GetPropertyDictionaryKey(*set_it), GetPropertySchemaHandle(*set_it)); |
| match = false; |
| } |
| |
| return match; |
| } |
| |
| WEAVE_ERROR TestTdmSink::OnEvent(uint16_t aType, void *aInParam) |
| { |
| InEventParam *inParam = static_cast<InEventParam *>(aInParam); |
| |
| switch (aType) { |
| case kEventDictionaryItemDelete: |
| WeaveLogDetail(DataManagement, "[TestTdmSink::OnEvent] Deleting %u:%u", GetPropertyDictionaryKey(inParam->mDictionaryItemDelete.mTargetHandle), GetPropertySchemaHandle(inParam->mDictionaryItemDelete.mTargetHandle)); |
| mDeletedHandles.insert(inParam->mDictionaryItemDelete.mTargetHandle); |
| break; |
| |
| case kEventDictionaryItemModifyBegin: |
| WeaveLogDetail(DataManagement, "[TestTdmSink::OnEvent] Adding/Modifying %u:%u", GetPropertyDictionaryKey(inParam->mDictionaryItemModifyBegin.mTargetHandle), GetPropertySchemaHandle(inParam->mDictionaryItemModifyBegin.mTargetHandle)); |
| break; |
| |
| case kEventDictionaryReplaceBegin: |
| WeaveLogDetail(DataManagement, "[TestTdmSink::OnEvent] Replacing %u:%u", GetPropertyDictionaryKey(inParam->mDictionaryReplaceBegin.mTargetHandle), GetPropertySchemaHandle(inParam->mDictionaryReplaceBegin.mTargetHandle)); |
| mReplacedDictionaries.insert(inParam->mDictionaryReplaceBegin.mTargetHandle); |
| break; |
| } |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR TestTdmSink::SetLeafData(PropertyPathHandle aHandle, TLVReader &aReader) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| uint16_t val; |
| |
| err = aReader.Get(val); |
| SuccessOrExit(err); |
| |
| WeaveLogDetail(DataManagement, "[TestTdmSink::SetLeafData] << %u:%u = %u", GetPropertyDictionaryKey(aHandle), GetPropertySchemaHandle(aHandle), val); |
| mModifiedHandles[aHandle] = val; |
| |
| exit: |
| return err; |
| } |
| |
| class TestTdm { |
| public: |
| TestTdm(); |
| |
| int Setup(); |
| int Teardown(); |
| int Reset(); |
| int BuildAndProcessNotify(); |
| |
| void TestTdmStatic_SingleLeafHandle(nlTestSuite *inSuite); |
| void TestTdmStatic_SingleLevelMerge(nlTestSuite *inSuite); |
| void TestTdmStatic_SingleLevelMergeDeep(nlTestSuite *inSuite); |
| void TestTdmStatic_DirtyStruct(nlTestSuite *inSuite); |
| void TestTdmStatic_DirtyLeafUnevenDepth(nlTestSuite *inSuite); |
| void TestTdmStatic_MergeHandleSetOverflow(nlTestSuite *inSuite); |
| void TestTdmStatic_MarkLeafHandleDirtyTwice(nlTestSuite *inSuite); |
| |
| void TestTdmStatic_TestNullableLeaf(nlTestSuite *inSuite); |
| void TestTdmStatic_TestNullableStruct(nlTestSuite *inSuite); |
| void TestTdmStatic_TestNonNullableLeaf(nlTestSuite *inSuite); |
| |
| void TestTdmStatic_TestEphemeralLeaf(nlTestSuite *inSuite); |
| void TestTdmStatic_TestEphemeralStruct(nlTestSuite *inSuite); |
| |
| void TestTdmMismatched_PathInDataElement(nlTestSuite *inSuite); |
| void TestTdmMismatched_TopLevelPOD(nlTestSuite *inSuite); |
| void TestTdmMismatched_NestedStruct(nlTestSuite *inSuite); |
| void TestTdmMismatched_TopLevelStruct(nlTestSuite *inSuite); |
| void TestTdmMismatched_SetLeafDataMismatch(nlTestSuite *inSuite); |
| |
| void TestTdmDictionary_DictionaryEntryAddition(nlTestSuite *inSuite); |
| void TestTdmDictionary_DictionaryEntriesAddition(nlTestSuite *inSuite); |
| void TestTdmDictionary_ReplaceDictionary(nlTestSuite *inSuite); |
| |
| void TestTdmDictionary_DeleteSingle(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteMultiple(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteHandleSetOverflow(nlTestSuite *inSuite); |
| void TestTdmDictionary_AddDeleteDifferent(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteAndMarkDirty(nlTestSuite *inSuite); |
| void TestTdmDictionary_MarkDirtyAndDelete(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteAndMarkFarDirty(nlTestSuite *inSuite); |
| void TestTdmDictionary_AddAndDeleteSimilar(nlTestSuite *inSuite); |
| void TestTdmDictionary_ModifyAndDeleteSimilar(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteAndModifySimilar(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteAndModifyLeafSimilar(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteStoreOverflowAndItemAddition(nlTestSuite *inSuite); |
| void TestTdmDictionary_DirtyStoreOverflowAndItemDeletion(nlTestSuite *inSuite); |
| void TestTdmDictionary_DeleteEntryTwice(nlTestSuite *inSuite); |
| |
| void TestTdmStatic_MultiInstance(nlTestSuite *inSuite); |
| |
| |
| private: |
| SubscriptionHandler *mSubHandler; |
| SubscriptionClient *mSubClient; |
| NotificationEngine *mNotificationEngine; |
| |
| SubscriptionEngine mSubscriptionEngine; |
| WeaveExchangeManager mExchangeMgr; |
| SingleResourceSourceTraitCatalog::CatalogItem mSourceCatalogStore[4]; |
| SingleResourceSourceTraitCatalog mSourceCatalog; |
| SingleResourceSinkTraitCatalog::CatalogItem mSinkCatalogStore[4]; |
| SingleResourceSinkTraitCatalog mSinkCatalog; |
| TestTdmSource mTestTdmSource; |
| TestTdmSource mTestTdmSource1; |
| TestTdmSink mTestTdmSink; |
| TestTdmSink mTestTdmSink1; |
| TestMismatchedCTraitDataSource mMismatchedTestCSource; |
| TestCTraitDataSink mTestCSink; |
| TestMismatchedCTraitDataSink mMismatchedTestCSink; |
| |
| TestBTraitDataSource mTestBSource; |
| TestBTraitDataSink mTestBSink; |
| |
| Binding *mClientBinding; |
| |
| uint32_t mTestCase; |
| }; |
| |
| TestTdm::TestTdm() |
| : mSourceCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID), mSourceCatalogStore, 4), |
| mSinkCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID), mSinkCatalogStore, 4), |
| mClientBinding(NULL) |
| { |
| mTestCase = 0; |
| } |
| |
| int TestTdm::Setup() |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TraitDataHandle testTdmSourceHandle; |
| TraitDataHandle testTdmSourceHandle1; |
| TraitDataHandle testTdmSinkHandle; |
| TraitDataHandle testTdmSinkHandle1; |
| TraitDataHandle testMismatchedCSourceHandle; |
| TraitDataHandle testCSinkHandle; |
| TraitDataHandle testBSourceHandle, testBSinkHandle; |
| SubscriptionHandler::TraitInstanceInfo *traitInstance = NULL; |
| |
| gSubscriptionEngine = &mSubscriptionEngine; |
| |
| // Initialize SubEngine and set it up |
| err = mSubscriptionEngine.Init(&ExchangeMgr, NULL, NULL); |
| SuccessOrExit(err); |
| |
| err = mSubscriptionEngine.EnablePublisher(NULL, &mSourceCatalog); |
| SuccessOrExit(err); |
| |
| // Get a sub handler and prime it to the right state |
| err = mSubscriptionEngine.NewSubscriptionHandler(&mSubHandler); |
| SuccessOrExit(err); |
| |
| mSubHandler->mBinding = ExchangeMgr.NewBinding(); |
| mSubHandler->mBinding->BeginConfiguration().Transport_UDP(); |
| |
| mClientBinding = ExchangeMgr.NewBinding(); |
| |
| err = mSubscriptionEngine.NewClient(&mSubClient, mClientBinding, NULL, NULL, &mSinkCatalog, 0); |
| SuccessOrExit(err); |
| |
| mNotificationEngine = &mSubscriptionEngine.mNotificationEngine; |
| |
| mSourceCatalog.Add(0, &mTestTdmSource, testTdmSourceHandle); |
| mSourceCatalog.Add(1, &mTestTdmSource1, testTdmSourceHandle1); |
| |
| mSourceCatalog.Add(2, &mMismatchedTestCSource, testMismatchedCSourceHandle); |
| |
| mSourceCatalog.Add(3, &mTestBSource, testBSourceHandle); |
| |
| mSinkCatalog.Add(0, &mTestTdmSink, testTdmSinkHandle); |
| mSinkCatalog.Add(1, &mTestTdmSink1, testTdmSinkHandle1); |
| |
| mSinkCatalog.Add(2, &mTestCSink, testCSinkHandle); |
| |
| mSinkCatalog.Add(3, &mTestBSink, testBSinkHandle); |
| |
| traitInstance = mSubscriptionEngine.mTraitInfoPool; |
| mSubHandler->mTraitInstanceList = traitInstance; |
| mSubHandler->mNumTraitInstances++; |
| ++(SubscriptionEngine::GetInstance()->mNumTraitInfosInPool); |
| |
| traitInstance->Init(); |
| traitInstance->mTraitDataHandle = testTdmSourceHandle; |
| traitInstance->mRequestedVersion = 1; |
| |
| traitInstance = mSubscriptionEngine.mTraitInfoPool + 1; |
| mSubHandler->mNumTraitInstances++; |
| ++(SubscriptionEngine::GetInstance()->mNumTraitInfosInPool); |
| |
| traitInstance->Init(); |
| traitInstance->mTraitDataHandle = testTdmSourceHandle1; |
| traitInstance->mRequestedVersion = 1; |
| |
| traitInstance = mSubscriptionEngine.mTraitInfoPool + 2; |
| mSubHandler->mNumTraitInstances++; |
| ++(SubscriptionEngine::GetInstance()->mNumTraitInfosInPool); |
| |
| traitInstance->Init(); |
| traitInstance->mTraitDataHandle = testMismatchedCSourceHandle; |
| traitInstance->mRequestedVersion = 1; |
| |
| traitInstance = mSubscriptionEngine.mTraitInfoPool + 3; |
| mSubHandler->mNumTraitInstances++; |
| ++(SubscriptionEngine::GetInstance()->mNumTraitInfosInPool); |
| |
| traitInstance->Init(); |
| traitInstance->mTraitDataHandle = testBSourceHandle; |
| traitInstance->mRequestedVersion = 1; |
| |
| exit: |
| if (err != WEAVE_NO_ERROR) { |
| WeaveLogError(DataManagement, "Error setting up test: %d", err); |
| } |
| |
| return err; |
| } |
| |
| int TestTdm::Teardown() |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| if (mClientBinding != NULL) |
| { |
| mClientBinding->Release(); |
| mClientBinding = NULL; |
| } |
| |
| return err; |
| } |
| |
| int TestTdm::Reset() |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| mSubHandler->MoveToState(SubscriptionHandler::kState_SubscriptionEstablished_Idle); |
| mTestTdmSink.Reset(); |
| mTestTdmSink1.Reset(); |
| |
| mTestTdmSource.Reset(); |
| mTestTdmSource1.Reset(); |
| |
| mMismatchedTestCSource.Reset(); |
| mTestCSink.Reset(); |
| |
| mTestBSink.Reset(); |
| mTestBSource.Reset(); |
| |
| mNotificationEngine->mGraphSolver.ClearDirty(); |
| |
| return err; |
| } |
| |
| int TestTdm::BuildAndProcessNotify() |
| { |
| bool isSubscriptionClean; |
| NotificationEngine::NotifyRequestBuilder notifyRequest; |
| NotificationRequest::Parser notify; |
| PacketBuffer *buf = NULL; |
| TLVWriter writer; |
| TLVReader reader; |
| TLVType dummyType1, dummyType2; |
| WEAVE_ERROR err; |
| bool neWriteInProgress = false; |
| |
| notifyRequest.Init(&buf, &writer, mSubHandler); |
| |
| err = mNotificationEngine->BuildSingleNotifyRequestDataList(mSubHandler, notifyRequest, isSubscriptionClean, neWriteInProgress); |
| SuccessOrExit(err); |
| |
| if (neWriteInProgress) |
| { |
| err = notifyRequest.MoveToState(NotificationEngine::kNotifyRequestBuilder_Idle); |
| SuccessOrExit(err); |
| |
| reader.Init(buf); |
| |
| err = reader.Next(); |
| SuccessOrExit(err); |
| |
| notify.Init(reader); |
| |
| err = notify.CheckSchemaValidity(); |
| SuccessOrExit(err); |
| |
| // Enter the struct |
| err = reader.EnterContainer(dummyType1); |
| SuccessOrExit(err); |
| |
| // SubscriptionId |
| err = reader.Next(); |
| SuccessOrExit(err); |
| |
| err = reader.Next(); |
| SuccessOrExit(err); |
| |
| VerifyOrExit(nl::Weave::TLV::kTLVType_Array == reader.GetType(), err = WEAVE_ERROR_WRONG_TLV_TYPE); |
| |
| err = reader.EnterContainer(dummyType2); |
| SuccessOrExit(err); |
| |
| err = mSubClient->ProcessDataList(reader); |
| SuccessOrExit(err); |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "nothing has been written"); |
| } |
| |
| exit: |
| if (buf) { |
| PacketBuffer::Free(buf); |
| } |
| |
| return err; |
| } |
| |
| void TestTdm::TestTdmStatic_MultiInstance(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_A, 2); |
| mTestTdmSource1.SetValue(TestHTrait::kPropertyHandle_B, 2); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_A, 2 } }, |
| { }, |
| { } ); |
| VerifyOrExit(testPass, ); |
| |
| testPass = mTestTdmSink1.ValidateChangeSets( { { TestHTrait::kPropertyHandle_B, 2 } }, |
| { }, |
| { } ); |
| VerifyOrExit(testPass, ); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_SingleLeafHandle(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_A, 2); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_A, 2 } }, |
| { }, |
| { } ); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_SingleLevelMerge(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_B, 2); |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_A, 2); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_B, 2 }, { TestHTrait::kPropertyHandle_A, 2 } }, |
| { }, |
| { }); |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_SingleLevelMergeDeep(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_K_Sb, 2); |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_K_Sc, 2); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_K_Sb, 2 }, { TestHTrait::kPropertyHandle_K_Sc, 2 } }, |
| { }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_DirtyStruct(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_K); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_K_Sb, 1 }, { TestHTrait::kPropertyHandle_K_Sc, 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_K_Sa }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_DirtyLeafUnevenDepth(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_A); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_K_Sb); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_A, 1 }, { TestHTrait::kPropertyHandle_K_Sb, 1 }, |
| { TestHTrait::kPropertyHandle_K_Sc, 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_K_Sa } ); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| |
| void TestTdm::TestTdmStatic_MergeHandleSetOverflow(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| // This should overflow the 4 merge handle set limitation, resulting in root being marked dirty. |
| // **NOTE** If you increase this merge handle limit, then this test will have to be altered too! |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_A); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_B); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_C); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_D); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_E); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_F); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_A, 1 }, { TestHTrait::kPropertyHandle_B, 1 }, |
| { TestHTrait::kPropertyHandle_C, 1 }, { TestHTrait::kPropertyHandle_D, 1 }, |
| { TestHTrait::kPropertyHandle_E, 1 }, { TestHTrait::kPropertyHandle_F, 1 }, |
| { TestHTrait::kPropertyHandle_G, 1 }, { TestHTrait::kPropertyHandle_H, 1 }, |
| { TestHTrait::kPropertyHandle_I, 1 }, { TestHTrait::kPropertyHandle_J, 1 }, |
| { TestHTrait::kPropertyHandle_K_Sb, 1 }, { TestHTrait::kPropertyHandle_K_Sc, 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_K_Sa, TestHTrait::kPropertyHandle_L }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_MarkLeafHandleDirtyTwice(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_A, 2); |
| mTestTdmSource.SetValue(TestHTrait::kPropertyHandle_A, 2); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_A, 2 } }, |
| { }, |
| { } ); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmStatic_TestNullableLeaf(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| mTestBSource.SetNullifiedPath(TestBTrait::kPropertyHandle_TaD_SaA, true); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleNull(TestBTrait::kPropertyHandle_TaD_SaA)); |
| |
| // set value and re-test |
| mTestBSource.SetNullifiedPath(TestBTrait::kPropertyHandle_TaD_SaA, false); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleNull(TestBTrait::kPropertyHandle_TaD_SaA) == false); |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleSet(TestBTrait::kPropertyHandle_TaD_SaA)); |
| } |
| |
| void TestTdm::TestTdmStatic_TestNullableStruct(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool anyChildrenSet = false; |
| Reset(); |
| |
| mTestBSource.SetNullifiedPath(TestBTrait::kPropertyHandle_TaD, true); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleNull(TestBTrait::kPropertyHandle_TaD)); |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleSet(TestBTrait::kPropertyHandle_TaD)); |
| |
| for (PropertyPathHandle i = TestBTrait::kPropertyHandle_TaD_SaA; i <= TestBTrait::kPropertyHandle_TaD_SaB; i++) |
| { |
| anyChildrenSet |= mTestBSink.IsPathHandleSet(i); |
| } |
| NL_TEST_ASSERT(inSuite, anyChildrenSet == false); |
| } |
| |
| void TestTdm::TestTdmStatic_TestNonNullableLeaf(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| Reset(); |
| |
| mTestBSource.SetNullifiedPath(TestBTrait::kPropertyHandle_TbB_SbB, true); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_WDM_SCHEMA_MISMATCH); |
| } |
| |
| void TestTdm::TestTdmStatic_TestEphemeralLeaf(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| mTestBSource.SetPresentPath(TestBTrait::kPropertyHandle_TaD_SaA, false); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleSet(TestBTrait::kPropertyHandle_TaD_SaA) == false); |
| } |
| |
| void TestTdm::TestTdmStatic_TestEphemeralStruct(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool anyChildrenSet = false; |
| Reset(); |
| |
| mTestBSource.SetPresentPath(TestBTrait::kPropertyHandle_TaD, false); |
| mTestBSource.SetDirty(TestBTrait::kPropertyHandle_Root); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mTestBSink.IsPathHandleSet(TestBTrait::kPropertyHandle_TaD) == false); |
| for (PropertyPathHandle i = TestBTrait::kPropertyHandle_TaD_SaA; i <= TestBTrait::kPropertyHandle_TaD_SaB; i++) |
| { |
| anyChildrenSet |= mTestBSink.IsPathHandleSet(i); |
| } |
| NL_TEST_ASSERT(inSuite, anyChildrenSet == false); |
| } |
| |
| void TestTdm::TestTdmMismatched_PathInDataElement(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| // set tc_d (unknown to subscriber) - path in DataElement will be unrecognizable |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcE_ScA, 10); |
| |
| err = BuildAndProcessNotify(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // no leaf data should be set |
| NL_TEST_ASSERT(inSuite, mTestCSink.WasAnyPathHandleSet() == false); |
| } |
| |
| void TestTdm::TestTdmMismatched_TopLevelPOD(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| // set tc_a (known to subscriber) and tc_d (unknown to subscriber) |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcA, 10); |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcE_ScA, 10); |
| |
| err = BuildAndProcessNotify(); |
| // SetLeafData returns error for unrecognized paths |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // check known path is successfully set |
| NL_TEST_ASSERT(inSuite, mTestCSink.WasPathHandleSet(TestCTrait::kPropertyHandle_TcA)); |
| } |
| |
| void TestTdm::TestTdmMismatched_NestedStruct(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| // set tc_c.ScA (known to subscriber) and tc_c.ScC (unknown to subscriber) |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcC_ScA, 10); |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcC_ScC, 10); |
| |
| err = BuildAndProcessNotify(); |
| // SetLeafData returns error for unrecognized paths |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // check known path is successfully set |
| NL_TEST_ASSERT(inSuite, mTestCSink.WasPathHandleSet(TestCTrait::kPropertyHandle_TcC_ScA)); |
| } |
| |
| void TestTdm::TestTdmMismatched_TopLevelStruct(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Reset(); |
| |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcA, 10); |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcE_ScA, 10); |
| |
| err = BuildAndProcessNotify(); |
| // SetLeafData returns error for unrecognized paths |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // check known path is successfully set |
| NL_TEST_ASSERT(inSuite, mTestCSink.WasPathHandleSet(TestCTrait::kPropertyHandle_TcA)); |
| } |
| |
| void TestTdm::TestTdmMismatched_SetLeafDataMismatch(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TraitDataHandle mismatchedTestCSinkHandle; |
| Reset(); |
| |
| // sub out mTestCSink for mMismatchedTestCSink |
| mSinkCatalog.Remove(2); |
| mSinkCatalog.Add(2, &mMismatchedTestCSink, mismatchedTestCSinkHandle); |
| |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcA, 10); |
| mMismatchedTestCSource.SetValue(TestMismatchedCTrait::kPropertyHandle_TcE_ScA, 10); |
| |
| err = BuildAndProcessNotify(); |
| // SetLeafData returns error for unrecognized paths |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, mMismatchedTestCSink.WasPathHandleSet(TestMismatchedCTrait::kPropertyHandle_TcE_ScA)); |
| } |
| |
| void TestTdm::TestTdmDictionary_DictionaryEntryAddition(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 0), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 0), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 0), 1 } }, |
| { }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DictionaryEntriesAddition(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 2), 1 } }, |
| { }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_ReplaceDictionary(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_L); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 0), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 0), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 0), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 2), 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_L }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteSingle(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(2); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| mTestTdmSink.DumpChangeSets(); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteMultiple(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(2); |
| mTestTdmSource.mDictlValues.erase(1); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2), CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteHandleSetOverflow(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| // We overflow the delete handle set, which should result in a replace of the parent dictionary. |
| // Thus, we should be getting a replace + all the elements in the dictionary |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[3] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[4] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(0); |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.mDictlValues.erase(2); |
| mTestTdmSource.mDictlValues.erase(3); |
| mTestTdmSource.mDictlValues.erase(4); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 4)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { }, |
| { TestHTrait::kPropertyHandle_L }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| |
| void TestTdm::TestTdmDictionary_AddDeleteDifferent(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(0); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0)); |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 } }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteAndMarkDirty(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(0); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0)); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_L); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_L }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_MarkDirtyAndDelete(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_L); |
| |
| mTestTdmSource.mDictlValues.erase(0); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 0)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_L }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteAndMarkFarDirty(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictSaValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictSaValues[1] = { 1, 1, 1 }; |
| |
| mTestTdmSource.mDictSaValues.erase(0); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_K_Sa_Value, 0)); |
| mTestTdmSource.SetDirty(TestHTrait::kPropertyHandle_K_Sb); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { TestHTrait::kPropertyHandle_K_Sb, 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_K_Sa_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_K_Sa_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_K_Sa_Value_Dc, 1), 1 } }, |
| { }, |
| { TestHTrait::kPropertyHandle_K_Sa }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_AddAndDeleteSimilar(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| |
| void TestTdm::TestTdmDictionary_ModifyAndDeleteSimilar(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| |
| mTestTdmSource.mDictlValues[1] = { 2, 2, 2 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteAndModifySimilar(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| mTestTdmSource.mDictlValues[1] = { 2, 2, 2 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 2 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 2 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 2 } }, |
| { }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteAndModifyLeafSimilar(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| |
| mTestTdmSource.mDictlValues[1] = { 2, 2, 2 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 2 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 2 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 2 } }, |
| { }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteStoreOverflowAndItemAddition(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource1.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[3] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[4] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[5] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[6] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[7] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[8] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[9] = { 1, 1, 1 }; |
| |
| // we have to start by adding a handle from another trait to set up the interference. |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[3] = { 1, 1, 1 }; |
| |
| // then we add a couple of dictionary additions to the trait in question |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| |
| // then we fill it up past the store's capacity with the interference trait till it overflows, |
| // resulting in the eviction of all of those entries associated with the interference trait. |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 4)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 5)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 6)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 7)); |
| mTestTdmSource1.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 8)); |
| |
| // Now finally, we put the delete in for the last item we added to the trait under test. |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| mTestTdmSink1.DumpChangeSets(); |
| printf("\n"); |
| mTestTdmSink.DumpChangeSets(); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 1), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 2), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 2), 1 } }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DirtyStoreOverflowAndItemDeletion(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource1.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[3] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[4] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[5] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[6] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[7] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[8] = { 1, 1, 1 }; |
| mTestTdmSource1.mDictlValues[9] = { 1, 1, 1 }; |
| |
| mTestTdmSource1.mDictlValues.erase(1); |
| mTestTdmSource1.mDictlValues.erase(2); |
| |
| // we have to start by adding a handle from another trait to set up the interference. |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[3] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(1); |
| mTestTdmSource.mDictlValues.erase(2); |
| mTestTdmSource.mDictlValues.erase(3); |
| |
| // then we add a couple of dictionary deletions to the trait in question |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| |
| // then we fill it up past the store's capacity with the interference trait till it overflows, |
| // resulting in the eviction of all of those entries associated with the interference trait. |
| mTestTdmSource1.mDictlValues.erase(3); |
| mTestTdmSource1.mDictlValues.erase(4); |
| mTestTdmSource1.mDictlValues.erase(5); |
| mTestTdmSource1.mDictlValues.erase(6); |
| mTestTdmSource1.mDictlValues.erase(7); |
| mTestTdmSource1.mDictlValues.erase(8); |
| |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 4)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 5)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 6)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 7)); |
| mTestTdmSource1.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 8)); |
| |
| // Now finally, we put the addition in for the last item we added to. |
| mTestTdmSource.mDictlValues[3] = { 1, 1, 1 }; |
| mTestTdmSource.SetDirty(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 3)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| mTestTdmSink1.DumpChangeSets(); |
| printf("\n"); |
| mTestTdmSink.DumpChangeSets(); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Da, 3), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Db, 3), 1 }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value_Dc, 3), 1 } }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 1), CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2) }, |
| { }); |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| void TestTdm::TestTdmDictionary_DeleteEntryTwice(nlTestSuite *inSuite) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| bool testPass = false; |
| |
| Reset(); |
| |
| mTestTdmSource.mDictlValues[0] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[1] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues[2] = { 1, 1, 1 }; |
| mTestTdmSource.mDictlValues.erase(2); |
| |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| mTestTdmSource.DeleteKey(CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2)); |
| |
| err = BuildAndProcessNotify(); |
| SuccessOrExit(err); |
| |
| mTestTdmSink.DumpChangeSets(); |
| |
| testPass = mTestTdmSink.ValidateChangeSets( { }, |
| { CreatePropertyPathHandle(TestHTrait::kPropertyHandle_L_Value, 2) }, |
| { }); |
| |
| |
| exit: |
| NL_TEST_ASSERT(inSuite, testPass); |
| } |
| |
| } // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) |
| } |
| } |
| } |
| |
| TestTdm *gTestTdm; |
| |
| /** |
| * Set up the test suite. |
| */ |
| static int TestSetup(void *inContext) |
| { |
| static TestTdm testTdm; |
| gTestTdm = &testTdm; |
| |
| return testTdm.Setup(); |
| } |
| |
| /** |
| * Tear down the test suite. |
| */ |
| static int TestTeardown(void *inContext) |
| { |
| return gTestTdm->Teardown(); |
| } |
| |
| static void TestTdmStatic_SingleLeafHandle(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_SingleLeafHandle(inSuite); |
| } |
| |
| static void TestTdmStatic_SingleLevelMerge(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_SingleLevelMerge(inSuite); |
| } |
| |
| static void TestTdmStatic_SingleLevelMergeDeep(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_SingleLevelMergeDeep(inSuite); |
| } |
| |
| static void TestTdmStatic_DirtyStruct(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_DirtyStruct(inSuite); |
| } |
| |
| static void TestTdmStatic_DirtyLeafUnevenDepth(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_DirtyLeafUnevenDepth(inSuite); |
| } |
| |
| static void TestTdmStatic_MergeHandleSetOverflow(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_MergeHandleSetOverflow(inSuite); |
| } |
| |
| static void TestTdmStatic_MarkLeafHandleDirtyTwice(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_MarkLeafHandleDirtyTwice(inSuite); |
| } |
| |
| static void TestTdmStatic_TestNullableStruct(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_TestNullableStruct(inSuite); |
| } |
| |
| static void TestTdmStatic_TestNullableLeaf(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_TestNullableLeaf(inSuite); |
| } |
| |
| static void TestTdmStatic_TestNonNullableLeaf(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_TestNonNullableLeaf(inSuite); |
| } |
| |
| static void TestTdmStatic_TestEphemeralStruct(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_TestEphemeralStruct(inSuite); |
| } |
| |
| static void TestTdmStatic_TestEphemeralLeaf(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_TestEphemeralLeaf(inSuite); |
| } |
| |
| static void TestTdmMismatched_PathInDataElement(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmMismatched_PathInDataElement(inSuite); |
| } |
| |
| static void TestTdmMismatched_TopLevelPOD(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmMismatched_TopLevelPOD(inSuite); |
| } |
| |
| static void TestTdmMismatched_NestedStruct(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmMismatched_NestedStruct(inSuite); |
| } |
| |
| static void TestTdmMismatched_TopLevelStruct(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmMismatched_TopLevelStruct(inSuite); |
| } |
| |
| static void TestTdmMismatched_SetLeafDataMismatch(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmMismatched_SetLeafDataMismatch(inSuite); |
| } |
| static void TestTdmDictionary_DictionaryEntryAddition(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DictionaryEntryAddition(inSuite); |
| } |
| |
| static void TestTdmDictionary_DictionaryEntriesAddition(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DictionaryEntriesAddition(inSuite); |
| } |
| |
| static void TestTdmDictionary_ReplaceDictionary(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_ReplaceDictionary(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteSingle(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteSingle(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteMultiple(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteMultiple(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteHandleSetOverflow(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteHandleSetOverflow(inSuite); |
| } |
| |
| static void TestTdmDictionary_AddDeleteDifferent(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_AddDeleteDifferent(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteAndMarkDirty(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteAndMarkDirty(inSuite); |
| } |
| |
| static void TestTdmDictionary_MarkDirtyAndDelete(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_MarkDirtyAndDelete(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteAndMarkFarDirty(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteAndMarkFarDirty(inSuite); |
| } |
| |
| static void TestTdmDictionary_AddAndDeleteSimilar(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_AddAndDeleteSimilar(inSuite); |
| } |
| |
| static void TestTdmDictionary_ModifyAndDeleteSimilar(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_ModifyAndDeleteSimilar(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteAndModifySimilar(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteAndModifySimilar(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteAndModifyLeafSimilar(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteAndModifyLeafSimilar(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteStoreOverflowAndItemAddition(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteStoreOverflowAndItemAddition(inSuite); |
| } |
| |
| static void TestTdmDictionary_DirtyStoreOverflowAndItemDeletion(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DirtyStoreOverflowAndItemDeletion(inSuite); |
| } |
| |
| static void TestTdmDictionary_DeleteEntryTwice(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmDictionary_DeleteEntryTwice(inSuite); |
| } |
| |
| static void TestTdmStatic_MultiInstance(nlTestSuite *inSuite, void *inContext) |
| { |
| gTestTdm->TestTdmStatic_MultiInstance(inSuite); |
| } |
| |
| /** |
| * Main |
| */ |
| int main(int argc, char *argv[]) |
| { |
| #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
| lwip_init(); |
| #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
| |
| nl::Weave::MockPlatform::gTestPlatformTimeFns.GetSystemTimeMs = Private::GetSystemTimeMs; |
| nl::Weave::MockPlatform::gTestPlatformTimeFns.SetSystemTime = Private::SetSystemTime; |
| |
| nlTestSuite theSuite = { |
| "weave-tdm", |
| &sTests[0], |
| TestSetup, |
| TestTeardown |
| }; |
| |
| // Generate machine-readable, comma-separated value (CSV) output. |
| nl_test_set_output_style(OUTPUT_CSV); |
| |
| // Run test suit against one context |
| nlTestRunner(&theSuite, NULL); |
| |
| return nlTestRunnerStats(&theSuite); |
| } |