| /* |
| * |
| * Copyright (c) 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 |
| * Unit tests for Weave Event Logging |
| * |
| */ |
| |
| #ifndef __STDC_FORMAT_MACROS |
| #define __STDC_FORMAT_MACROS |
| #endif |
| |
| #ifndef __STDC_LIMIT_MACROS |
| #define __STDC_LIMIT_MACROS |
| #endif |
| |
| #include <new> |
| #include <stdint.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| #include <nlbyteorder.h> |
| #include <nltest.h> |
| |
| // Note that the choice of namespace alias must be made up front for each and every compile unit |
| // This is because many include paths could set the default alias to unintended target. |
| #include <Weave/Profiles/bulk-data-transfer/Development/BDXManagedNamespace.hpp> |
| #include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h> |
| |
| #include "MockExternalEvents.h" |
| #include "ToolCommon.h" |
| #include "TestEventLoggingSchemaExamples.h" |
| #include <InetLayer/Inet.h> |
| #include <Weave/Core/WeaveCore.h> |
| #include <Weave/Core/WeaveMessageLayer.h> |
| #include <Weave/Core/WeaveEncoding.h> |
| #include <Weave/Core/WeaveTLV.h> |
| #include <Weave/Core/WeaveTLVDebug.hpp> |
| #include <Weave/Core/WeaveTLVUtilities.hpp> |
| #include <Weave/Core/WeaveTLVData.hpp> |
| #include <Weave/Core/WeaveSecurityMgr.h> |
| #include <Weave/Profiles/security/WeaveSecurity.h> |
| #include <Weave/Profiles/ProfileCommon.h> |
| #include <Weave/Profiles/time/WeaveTime.h> |
| |
| #include <Weave/Support/TraitEventUtils.h> |
| #include <Weave/Profiles/data-management/DataManagement.h> |
| #include <Weave/Support/ErrorStr.h> |
| |
| #include "TestPersistedStorageImplementation.h" |
| #include <Weave/Support/PersistedCounter.h> |
| |
| #include "schema/nest/test/trait/TestETrait.h" |
| #include "schema/nest/test/trait/TestCommonTrait.h" |
| |
| #include "TestPlatformTime.h" |
| |
| using namespace nl::Weave::TLV; |
| using namespace nl::Weave::Profiles::DataManagement; |
| |
| namespace Private { |
| |
| static bool sSystemTimeValid = true; |
| |
| static WEAVE_ERROR SetSystemTime(const nl::Weave::Profiles::Time::timesync_t timestamp_usec) |
| { |
| if (timestamp_usec != 0) |
| { |
| sSystemTimeValid = true; |
| } |
| else |
| { |
| sSystemTimeValid = false; |
| } |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| static WEAVE_ERROR GetSystemTimeMs(nl::Weave::Profiles::Time::timesync_t *p_timestamp_msec) |
| { |
| if (sSystemTimeValid) |
| { |
| *p_timestamp_msec = static_cast<nl::Weave::Profiles::Time::timesync_t>(nl::Weave::System::Timer::GetCurrentEpoch()); |
| } |
| else |
| { |
| *p_timestamp_msec = 0; |
| } |
| |
| 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) |
| |
| namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) { |
| |
| class TestSubscriptionHandler : public SubscriptionHandler |
| { |
| public: |
| TestSubscriptionHandler(void); |
| |
| bool CheckEventUpToDate(nl::Weave::Profiles::DataManagement::LoggingManagement &logger); |
| |
| nl::Weave::Profiles::DataManagement::ImportanceType FindNextImportanceForTransfer(void); |
| |
| WEAVE_ERROR SetEventLogEndpoint(nl::Weave::Profiles::DataManagement::LoggingManagement &logger); |
| |
| nl::Weave::Profiles::DataManagement::event_id_t & GetVendedEvent(nl::Weave::Profiles::DataManagement::ImportanceType inImportance); |
| |
| bool VerifyTraversingImportance(void); |
| |
| void SetActive(void) { mCurrentState = kState_Subscribing_Evaluating; } |
| void SetAborted(void) { mCurrentState = kState_Aborted; } |
| void SetEstablishedIdle(void) { mCurrentState = kState_SubscriptionEstablished_Idle; } |
| private: |
| /* important: this class must not add any members or declare virtual functions */ |
| }; |
| |
| |
| TestSubscriptionHandler::TestSubscriptionHandler(void) |
| { |
| InitAsFree(); |
| } |
| |
| bool TestSubscriptionHandler::CheckEventUpToDate(nl::Weave::Profiles::DataManagement::LoggingManagement &logger) |
| { |
| return SubscriptionHandler::CheckEventUpToDate(logger); |
| } |
| |
| bool TestSubscriptionHandler::VerifyTraversingImportance(void) |
| { |
| return FindNextImportanceForTransfer() == nl::Weave::Profiles::DataManagement::kImportanceType_Invalid; |
| } |
| |
| nl::Weave::Profiles::DataManagement::ImportanceType TestSubscriptionHandler::FindNextImportanceForTransfer(void) |
| { |
| return SubscriptionHandler::FindNextImportanceForTransfer(); |
| } |
| |
| WEAVE_ERROR TestSubscriptionHandler::SetEventLogEndpoint(nl::Weave::Profiles::DataManagement::LoggingManagement &logger) |
| { |
| return SubscriptionHandler::SetEventLogEndpoint(logger); |
| } |
| |
| nl::Weave::Profiles::DataManagement::event_id_t & TestSubscriptionHandler::GetVendedEvent(nl::Weave::Profiles::DataManagement::ImportanceType inImportance) |
| { |
| return mSelfVendedEvents[inImportance - nl::Weave::Profiles::DataManagement::kImportanceType_First]; |
| } |
| |
| SubscriptionEngine * SubscriptionEngine::GetInstance() |
| { |
| static SubscriptionEngine gWdmSubscriptionEngine; |
| |
| return &gWdmSubscriptionEngine; |
| } |
| |
| } // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) |
| } // Profiles |
| } // Weave |
| } // nl |
| |
| #define TOOL_NAME "TestDataLogging" |
| |
| // forward declarations for networking functions. They are |
| // implemented at the end of the file, as they are incidental to the |
| // test and are irrelevant unless the test is invoked in a mode that |
| // exercises the upload path (i.e. with a dest node ID, or a dest IP |
| // address. |
| |
| struct TestLoggingContext; |
| |
| static void PrepareBinding(TestLoggingContext *context); |
| static WEAVE_ERROR InitSubscriptionClient(TestLoggingContext *context); |
| static void HandleBindingEvent(void *const appState, const Binding::EventType event, const Binding::InEventParam &inParam, Binding::OutEventParam &outParam); |
| static void StartClientConnection(System::Layer *systemLayer, void *appState, System::Error err); |
| static void HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR conErr); |
| static void HandleConnectionClosed(WeaveConnection *con, WEAVE_ERROR conErr); |
| static WEAVE_ERROR FetchEventsHelper(TLVReader &aReader, event_id_t aEventId, uint8_t *aBackingStore, size_t aLen, ImportanceType aImportance = nl::Weave::Profiles::DataManagement::Production); |
| |
| static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg); |
| |
| const uint64_t kTestNodeId = 0x18B43000002DCF71ULL; |
| |
| // Globals used when the test is used in conjunction with BDX |
| |
| WeaveConnection *Con = NULL; |
| bool WaitingForBDXResp = false; |
| bool Listening = false; |
| bool Upload = true; // download by default |
| bool Debug = false; |
| uint32_t ConnectInterval = 200; //ms |
| uint32_t ConnectTry = 0; |
| uint32_t ConnectMaxTry = 3; |
| bool ClientConEstablished = false; |
| bool DestHostNameResolved = false; // only used for UDP |
| |
| static OptionDef gToolOptionDefs[] = |
| { |
| { "start-event-id", kArgumentRequired, 's' }, |
| { "block-size", kArgumentRequired, 'b' }, |
| { "dest-addr", kArgumentRequired, 'D' }, |
| { "parent-node-id", kArgumentRequired, 'p' }, |
| { "debug", kNoArgument, 'd' }, |
| { "tcp", kNoArgument, 't' }, |
| { "udp", kNoArgument, 'u' }, |
| { NULL } |
| }; |
| |
| static const char *const gToolOptionHelp = |
| " -p <num>, --parent-node-id <num> \n" |
| " Parent node id; the ID of the node that will receive the event\n" |
| " logs\n" |
| "\n" |
| " -D <ip-addr>, --dest-addr <ip-addr>\n" |
| " The IP address or hostname of the parent (the node that will\n" |
| " receive thise event log)\n" |
| " -t, --tcp \n" |
| " Use TCP for BDX session\n" |
| "\n" |
| " -u, --udp \n" |
| " Use UDP for BDX session\n" |
| "\n" |
| " -s <num>, --start-event-id <num>\n" |
| " Begin the offload of each event sequence at <num> event\n" |
| "\n" |
| " -b <num>, --block-size <num>\n" |
| " Block size to use for BDX upload.\n" |
| "\n" |
| " -d, --debug \n" |
| " Enable debug messages.\n" |
| "\n"; |
| |
| static OptionSet gToolOptions = |
| { |
| HandleOption, |
| gToolOptionDefs, |
| "GENERAL OPTIONS", |
| gToolOptionHelp |
| }; |
| |
| static HelpOptions gHelpOptions( |
| TOOL_NAME, |
| "Usage: " TOOL_NAME " [<options...>] <dest-node-id>[@<dest-host>[:<dest-port>][%<interface>]]\n" |
| " " TOOL_NAME " [<options...>] --listen\n", |
| WEAVE_VERSION_STRING "\n" WEAVE_TOOL_COPYRIGHT, |
| "Test event logging. Without any options, the program invokes a\n" |
| "suite of local log tests. The options enable testing of a log\n" |
| "upload over the BDX path.\n" |
| ); |
| |
| static OptionSet *gToolOptionSets[] = |
| { |
| &gToolOptions, |
| &gNetworkOptions, |
| &gWeaveNodeOptions, |
| &gFaultInjectionOptions, |
| &gHelpOptions, |
| NULL |
| }; |
| |
| struct BDXContext { |
| uint64_t DestNodeId; |
| IPAddress DestIPAddr; |
| const char *DestIPAddrStr; |
| uint32_t mStartingBlock; |
| bool mUseTCP; |
| bool mDone; |
| }; |
| |
| BDXContext gBDXContext; |
| |
| // Event test harness contex |
| |
| struct TestLoggingContext |
| { |
| bool mVerbose; |
| bool bdx; |
| bool bdxDone; |
| bool mReinitializeBDXUpload; |
| WeaveExchangeManager *mExchangeMgr; |
| Binding *mBinding; |
| SubscriptionClient *mSubClient; |
| TestLoggingContext(); |
| }; |
| |
| TestLoggingContext gTestLoggingContext; |
| |
| TestLoggingContext::TestLoggingContext() : |
| mVerbose(false), |
| bdx(false), |
| bdxDone(false), |
| mReinitializeBDXUpload(false), |
| mExchangeMgr(NULL), |
| mBinding(NULL), |
| mSubClient(NULL) |
| { |
| } |
| |
| LogBDXUpload gLogBDXUpload; |
| |
| // Example profiles for logging: |
| #define OpenCloseProfileID 0x235A00AA |
| #define kOpenCloseStateTag 0x01 |
| #define kBypassStateTag 0x02 |
| |
| enum OpenCloseStateEnum { |
| Unknown = 0, |
| Open = 1, |
| PartiallyOpen = 2, |
| Closed = 3, |
| }; |
| |
| enum BypassStateEnum { |
| BypassInactive = 0, |
| BypassActive = 1, |
| BypassExpired = 2, |
| }; |
| |
| struct TestOpenCloseState |
| { |
| TestOpenCloseState(); |
| void EvolveState(); |
| uint8_t mState; |
| uint8_t mBypass; |
| }; |
| |
| TestOpenCloseState gTestOpenCloseState; |
| |
| TestOpenCloseState::TestOpenCloseState() |
| { |
| mState = Closed; |
| mBypass = BypassInactive; |
| } |
| |
| void TestOpenCloseState::EvolveState(void) |
| { |
| if (mState == Closed) |
| { |
| mState = Open; |
| } |
| else |
| { |
| mState = Closed; |
| } |
| } |
| |
| const uint32_t gProfileList[] = { OpenCloseProfileID }; |
| |
| WEAVE_ERROR WriteOpenCloseState(nl::Weave::TLV::TLVWriter & writer, uint8_t inDataTag, void * anAppState) |
| { |
| TestOpenCloseState * state = NULL; |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| nl::Weave::TLV::TLVType openCloseState; |
| |
| VerifyOrExit(anAppState != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| state = static_cast<TestOpenCloseState *>(anAppState); |
| |
| err = writer.StartContainer(ContextTag(nl::Weave::Profiles::DataManagement::kTag_EventData), nl::Weave::TLV::kTLVType_Structure, openCloseState); |
| SuccessOrExit(err); |
| |
| err = writer.Put(nl::Weave::TLV::ContextTag(kOpenCloseStateTag), state->mState); |
| SuccessOrExit(err); |
| |
| err = writer.Put(nl::Weave::TLV::ContextTag(kBypassStateTag), state->mBypass); |
| SuccessOrExit(err); |
| |
| err = writer.EndContainer(openCloseState); |
| SuccessOrExit(err); |
| |
| err = writer.Finalize(); |
| |
| state->EvolveState(); |
| |
| exit: |
| return err; |
| } |
| |
| void SimpleDumpWriter(const char *aFormat, ...) |
| { |
| va_list args; |
| |
| va_start(args, aFormat); |
| |
| vprintf(aFormat, args); |
| |
| va_end(args); |
| } |
| |
| |
| WEAVE_ERROR LogBufferConsole(void *inAppState, PacketBuffer* inBuffer) |
| { |
| printf("Log entries:\nTime\tSchema\tEventData\n"); |
| nl::Weave::TLV::TLVReader reader; |
| uint8_t * p = inBuffer->Start(); |
| uint32_t time = *((uint32_t*) p); |
| uint16_t schema = *((uint16_t*) (p+4)); |
| |
| inBuffer->SetStart(p+6); |
| |
| reader.Init(inBuffer, inBuffer->TotalLength()); |
| printf("%d\t%d\t", time, schema); |
| nl::Weave::TLV::Debug::Dump(reader, SimpleDumpWriter); |
| return WEAVE_NO_ERROR; |
| |
| } |
| |
| // Maximally sized event envelope |
| #define EVENT_ENVELOPE_SIZE 26 |
| // Larger event payload. structured s.t. it fits in within the |
| // WEAVE_CONFIG_EVENT_SIZE_RESERVE (with the envelope) |
| #define EVENT_PAYLOAD_SIZE_1 128 |
| // Larger event payload. Structured s.t. it fits in the buffer, but |
| // it is larger than the WEAVE_CONFIG_SIZE_RESERVE |
| #define EVENT_PAYLOAD_SIZE_2 256 |
| #define EVENT_SIZE_1 EVENT_PAYLOAD_SIZE_1 + EVENT_ENVELOPE_SIZE |
| // Larger event payload. Doesn't fit in debug buffer. |
| #define EVENT_PAYLOAD_SIZE_3 (WEAVE_CONFIG_EVENT_SIZE_RESERVE + EVENT_SIZE_1) |
| |
| uint64_t gDebugEventBuffer[(sizeof(nl::Weave::Profiles::DataManagement::CircularEventBuffer) + WEAVE_CONFIG_EVENT_SIZE_RESERVE + EVENT_SIZE_1 + 7)/8]; |
| uint64_t gInfoEventBuffer[256]; |
| uint64_t gProdEventBuffer[256]; |
| uint64_t gCritEventBuffer[256]; |
| uint8_t gLargeMemoryBackingStore[16384]; |
| |
| static const uint32_t sEventIdCounterEpoch = 0x10000; |
| |
| static const char *sCritEventIdCounterStorageKey = "CritEIDC"; |
| static nl::Weave::PersistedCounter sCritEventIdCounter; |
| static const char *sProductionEventIdCounterStorageKey = "ProductionEIDC"; |
| static nl::Weave::PersistedCounter sProductionEventIdCounter; |
| static const char *sInfoEventIdCounterStorageKey = "InfoEIDC"; |
| static nl::Weave::PersistedCounter sInfoEventIdCounter; |
| static const char *sDebugEventIdCounterStorageKey = "DebugEIDC"; |
| static nl::Weave::PersistedCounter sDebugEventIdCounter; |
| |
| const char *sCounterKeys[kImportanceType_Last] = { |
| sCritEventIdCounterStorageKey, |
| sProductionEventIdCounterStorageKey, |
| sInfoEventIdCounterStorageKey, |
| sDebugEventIdCounterStorageKey, |
| }; |
| |
| const uint32_t sCounterEpochs[kImportanceType_Last] = { |
| sEventIdCounterEpoch, |
| sEventIdCounterEpoch, |
| sEventIdCounterEpoch, |
| sEventIdCounterEpoch, |
| }; |
| |
| PersistedCounter *sCounterStorage[kImportanceType_Last] = { |
| &sCritEventIdCounter, |
| &sProductionEventIdCounter, |
| &sInfoEventIdCounter, |
| &sDebugEventIdCounter, |
| }; |
| |
| void InitializeEventLogging(TestLoggingContext *context) |
| { |
| |
| size_t arraySizes[] = { sizeof(gDebugEventBuffer), sizeof(gInfoEventBuffer), sizeof(gProdEventBuffer) , sizeof(gCritEventBuffer) }; |
| |
| void *arrays[] = { |
| static_cast<void *>(&gDebugEventBuffer[0]), |
| static_cast<void *>(&gInfoEventBuffer[0]), |
| static_cast<void *>(&gProdEventBuffer[0]), |
| static_cast<void *>(&gCritEventBuffer[0]) }; |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement::CreateLoggingManagement(context->mExchangeMgr, sizeof(arrays)/sizeof(arrays[0]), &arraySizes[0], &arrays[0], NULL, NULL, NULL); |
| nl::Weave::Profiles::DataManagement::LoggingManagement &instance = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| nl::Weave::Profiles::DataManagement::LoggingConfiguration::GetInstance().mGlobalImportance = nl::Weave::Profiles::DataManagement::Debug; |
| new (&gLogBDXUpload)nl::Weave::Profiles::DataManagement::LogBDXUpload(); |
| gLogBDXUpload.Init(&instance); |
| } |
| |
| void DestroyEventLogging(TestLoggingContext *context) |
| { |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().DestroyLoggingManagement(); |
| |
| } |
| |
| void InitializeEventLoggingWithPersistedCounters(TestLoggingContext *context, uint32_t startingValue, nl::Weave::Profiles::DataManagement::ImportanceType globalImportance) |
| { |
| size_t arraySizes[] = { sizeof(gDebugEventBuffer), sizeof(gInfoEventBuffer), sizeof(gProdEventBuffer), sizeof(gCritEventBuffer[0]) }; |
| |
| void *arrays[] = { |
| static_cast<void *>(&gDebugEventBuffer[0]), |
| static_cast<void *>(&gInfoEventBuffer[0]), |
| static_cast<void *>(&gProdEventBuffer[0]), |
| static_cast<void *>(&gCritEventBuffer[0]) }; |
| |
| nl::Weave::Platform::PersistedStorage::Write(sCritEventIdCounterStorageKey, startingValue); |
| nl::Weave::Platform::PersistedStorage::Write(sProductionEventIdCounterStorageKey, startingValue); |
| nl::Weave::Platform::PersistedStorage::Write(sInfoEventIdCounterStorageKey, startingValue); |
| nl::Weave::Platform::PersistedStorage::Write(sDebugEventIdCounterStorageKey, startingValue); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement::CreateLoggingManagement(context->mExchangeMgr, sizeof(arrays)/sizeof(arrays[0]), &arraySizes[0], &arrays[0], sCounterKeys, sCounterEpochs, sCounterStorage); |
| |
| nl::Weave::Profiles::DataManagement::LoggingConfiguration::GetInstance().mGlobalImportance = globalImportance; |
| } |
| |
| void DumpEventLog(nlTestSuite *inSuite) |
| { |
| uint8_t backingStore[1024]; |
| size_t elementCount; |
| event_id_t eventId = 1; |
| TLVWriter writer; |
| TLVReader reader; |
| WEAVE_ERROR err; |
| writer.Init(backingStore, 1024); |
| |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(writer, nl::Weave::Profiles::DataManagement::Production, eventId); |
| if (err == WEAVE_NO_ERROR || err == WEAVE_END_OF_TLV) |
| { |
| printf("Successfully wrote %u bytes to the log\n", writer.GetLengthWritten()); |
| } |
| else |
| { |
| printf("Wrote %u bytes to the log, FetchEventsSince returned %s (%d)\n", writer.GetLengthWritten(), ErrorStr(err), err); |
| } |
| reader.Init(backingStore, 1024); |
| nl::Weave::TLV::Utilities::Count(reader, elementCount); |
| printf("Fetched %zu elements, last eventID: %u \n", elementCount, eventId); |
| nl::Weave::TLV::Debug::Dump(reader, SimpleDumpWriter); |
| } |
| |
| void DoBDXUpload(TestLoggingContext *context) |
| { |
| if (! context->bdx ) |
| { |
| return; |
| } |
| gBDXContext.mDone = false; |
| if (gBDXContext.mUseTCP) |
| { |
| SystemLayer.StartTimer(ConnectInterval, StartClientConnection, &gBDXContext); |
| } |
| else |
| { |
| PrepareBinding(context); |
| } |
| |
| while (!gBDXContext.mDone) |
| { |
| struct timeval sleepTime; |
| sleepTime.tv_sec = 0; |
| sleepTime.tv_usec = 100000; |
| |
| ServiceNetwork(sleepTime); |
| if (gLogBDXUpload.mState == nl::Weave::Profiles::DataManagement::LogBDXUpload::UploaderInitialized) |
| { |
| gBDXContext.mDone = true; |
| for (size_t i = 0; i < 1000; i++) |
| { |
| sleepTime.tv_sec = 0; |
| sleepTime.tv_usec = 1000; |
| |
| ServiceNetwork(sleepTime); |
| } |
| } |
| } |
| |
| gLogBDXUpload.Shutdown(); |
| |
| } |
| |
| |
| void PrintEventLog() |
| { |
| TLVReader reader; |
| size_t elementCount; |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().GetEventReader(reader, nl::Weave::Profiles::DataManagement::Production); |
| |
| nl::Weave::TLV::Utilities::Count(reader, elementCount); |
| printf("Found %lu elements\n", elementCount); |
| nl::Weave::TLV::Debug::Dump(reader, SimpleDumpWriter); |
| } |
| |
| static int TestSetup(void *inContext) |
| { |
| TestLoggingContext *ctx = static_cast<TestLoggingContext *>(inContext); |
| static WeaveFabricState sFabricState; |
| static WeaveExchangeManager sExchangeMgr; |
| |
| InitSystemLayer(); |
| if (ctx->bdx) |
| { |
| InitNetwork(); |
| InitWeaveStack(true, true); |
| |
| ctx->mExchangeMgr = &ExchangeMgr; |
| } |
| else |
| { |
| // fake Weave exchange layer. We are not running any |
| // networking tests, and at that point the only functionality |
| // required by the event logging subsystem is that the |
| // ExchageManager has a fabric state with a node id. |
| |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| #if WEAVE_SYSTEM_CONFIG_USE_LWIP |
| lwip_init(); |
| #endif // WEAVE_SYSTEM_CONFIG_USE_LWIP |
| |
| err = sFabricState.Init(); |
| if (err != WEAVE_NO_ERROR) |
| return FAILURE; |
| |
| sFabricState.LocalNodeId = kTestNodeId; |
| sExchangeMgr.FabricState = & sFabricState; |
| sExchangeMgr.State = WeaveExchangeManager::kState_Initialized; |
| ctx->mExchangeMgr = &sExchangeMgr; |
| } |
| |
| SubscriptionEngine::GetInstance()->Init(&ExchangeMgr, NULL, NULL); |
| |
| return SUCCESS; |
| } |
| |
| static int TestTeardown(void *inContext) |
| { |
| TestLoggingContext *ctx = static_cast<TestLoggingContext *>(inContext); |
| if (ctx->bdx) |
| { |
| ShutdownWeaveStack(); |
| ShutdownNetwork(); |
| ShutdownSystemLayer(); |
| } |
| return SUCCESS; |
| } |
| |
| static void CheckLogState(nlTestSuite *inSuite, |
| TestLoggingContext *inContext, |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt, |
| size_t expectedNumEvents) |
| { |
| WEAVE_ERROR err; |
| TLVReader reader; |
| size_t elementCount; |
| |
| err = logMgmt.GetEventReader(reader, nl::Weave::Profiles::DataManagement::Production); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::Weave::TLV::Utilities::Count(reader, elementCount, false); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, elementCount == expectedNumEvents); |
| if (inContext->mVerbose) |
| { |
| printf("Num Events: %lu\n", elementCount); |
| } |
| } |
| |
| static void CheckLogReadOut(nlTestSuite *inSuite, |
| TestLoggingContext *inContext, |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt, |
| nl::Weave::Profiles::DataManagement::ImportanceType importance, |
| event_id_t startingEventId, |
| size_t expectedNumEvents) |
| { |
| WEAVE_ERROR err; |
| TLVReader reader; |
| TLVWriter writer; |
| uint8_t backingStore[1024]; |
| size_t elementCount; |
| writer.Init(backingStore, 1024); |
| |
| err = logMgmt.FetchEventsSince(writer, importance, startingEventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR || err == WEAVE_END_OF_TLV); |
| |
| reader.Init(backingStore, writer.GetLengthWritten()); |
| |
| err = nl::Weave::TLV::Utilities::Count(reader, elementCount, false); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| NL_TEST_ASSERT(inSuite, elementCount == expectedNumEvents); |
| |
| if (inContext->mVerbose) |
| { |
| reader.Init(backingStore, writer.GetLengthWritten()); |
| printf("Starting Event ID: %u, Expected Events: %lu, Num Events: %lu, Num Bytes: %u\n", startingEventId, expectedNumEvents, elementCount, writer.GetLengthWritten()); |
| nl::Weave::TLV::Debug::Dump(reader, SimpleDumpWriter); |
| } |
| } |
| |
| static void CheckLogEventBasics(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid1, eid2, eid3; |
| EventSchema schema = { |
| OpenCloseProfileID, |
| 1, // Event type 1 |
| nl::Weave::Profiles::DataManagement::Production, |
| 1, |
| 1 |
| }; |
| |
| InitializeEventLogging(context); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| // Sample production events, spaced 10 milliseconds apart |
| eid1 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteOpenCloseState, |
| static_cast<void*> (&gTestOpenCloseState) |
| ); |
| CheckLogState(inSuite, context, logMgmt, 1); |
| |
| usleep(10000); |
| eid2 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteOpenCloseState, |
| static_cast<void*> (&gTestOpenCloseState) |
| ); |
| CheckLogState(inSuite, context, logMgmt, 2); |
| |
| usleep(10000); |
| eid3 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteOpenCloseState, |
| static_cast<void*> (&gTestOpenCloseState) |
| ); |
| CheckLogState(inSuite, context, logMgmt, 3); |
| |
| if (context->mVerbose) |
| { |
| PrintEventLog(); |
| } |
| NL_TEST_ASSERT(inSuite, (eid1 + 1) == eid2); |
| NL_TEST_ASSERT(inSuite, (eid2 + 1) == eid3); |
| |
| // Verify that the readout supports the expected volume of events |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid1, 3); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid2, 2); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid3, 1); |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| static void CheckLogFreeform(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid1, eid2, eid3; |
| size_t counter = 0; |
| InitializeEventLogging(context); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| // Sample production events, spaced 10 milliseconds apart |
| eid1 = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", counter++); |
| |
| CheckLogState(inSuite, context, logMgmt, 1); |
| |
| usleep(10000); |
| |
| eid2 = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", counter++); |
| CheckLogState(inSuite, context, logMgmt, 2); |
| |
| usleep(10000); |
| eid3 = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", counter++); |
| CheckLogState(inSuite, context, logMgmt, 3); |
| |
| if (context->mVerbose) |
| { |
| PrintEventLog(); |
| } |
| NL_TEST_ASSERT(inSuite, (eid1 + 1) == eid2); |
| NL_TEST_ASSERT(inSuite, (eid2 + 1) == eid3); |
| |
| // Verify that the readout supports the expected volume of events |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid1, 3); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid2, 2); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid3, 1); |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| static void CheckLogPreformed(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| event_id_t eid1, eid2, eid3; |
| EventSchema schema = { |
| OpenCloseProfileID, |
| 2, // Event type 2 |
| nl::Weave::Profiles::DataManagement::Production, |
| 1, |
| 1 |
| }; |
| |
| uint8_t backingStore[1024]; |
| TLVWriter writer; |
| TLVType containerType; |
| TLVReader reader; |
| |
| InitializeEventLogging(context); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| writer.Init(backingStore, 1024); |
| err = writer.StartContainer(AnonymousTag, kTLVType_Structure, containerType); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Put(ContextTag(1), false); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Put(ContextTag(2), true); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.EndContainer(containerType); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| |
| reader.Init(backingStore, writer.GetLengthWritten()); |
| |
| // Sample production events, spaced 10 milliseconds apart |
| eid1 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| reader |
| ); |
| |
| CheckLogState(inSuite, context, logMgmt, 1); |
| |
| usleep(10000); |
| reader.Init(backingStore, writer.GetLengthWritten()); |
| eid2 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| reader |
| ); |
| CheckLogState(inSuite, context, logMgmt, 2); |
| |
| usleep(10000); |
| reader.Init(backingStore, writer.GetLengthWritten()); |
| eid3 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| reader |
| ); |
| CheckLogState(inSuite, context, logMgmt, 3); |
| |
| if (context->mVerbose) |
| { |
| PrintEventLog(); |
| } |
| NL_TEST_ASSERT(inSuite, (eid1 + 1) == eid2); |
| NL_TEST_ASSERT(inSuite, (eid2 + 1) == eid3); |
| |
| // Verify that the readout supports the expected volume of events |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid1, 3); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid2, 2); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid3, 1); |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| #define kSampleEventTag_State 1 |
| #define kSampleEventTag_Timestamp 2 |
| #define kSampleEventTag_Structure 3 |
| #define kSampleEventTag_Samples 4 |
| |
| #define kEventStructTag_a 1 |
| #define kEventStructTag_b 2 |
| |
| #define kEventStatsTag_str 1 |
| |
| #define kDataManagementTag_EventData 50 |
| |
| static const uint8_t SampleEventEncoding[] = |
| { |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_FULLY_QUALIFIED_6Bytes(0x0A00, 1)), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kDataManagementTag_EventData)), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_State), 5), |
| nlWeaveTLV_UINT16(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Timestamp), 328), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Structure)), |
| nlWeaveTLV_BOOL(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStructTag_a), true), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStructTag_b)), |
| nlWeaveTLV_UTF8_STRING_1ByteLength(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStatsTag_str), 10), |
| 'b', 'l', 'o', 'o', 'p', 'b', 'l', 'o', 'o', 'p', |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_ARRAY(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Samples)), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 0), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 1), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 2), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 3), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 4), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_ANONYMOUS, 5), |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER |
| }; |
| |
| static const uint8_t SampleEmptyArrayEventEncoding[] = |
| { |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_FULLY_QUALIFIED_6Bytes(0x0A00, 1)), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kDataManagementTag_EventData)), |
| nlWeaveTLV_UINT8(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_State), 5), |
| nlWeaveTLV_UINT16(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Timestamp), 328), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Structure)), |
| nlWeaveTLV_BOOL(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStructTag_a), true), |
| nlWeaveTLV_STRUCTURE(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStructTag_b)), |
| nlWeaveTLV_UTF8_STRING_1ByteLength(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kEventStatsTag_str), 10), |
| 'b', 'l', 'o', 'o', 'p', 'b', 'l', 'o', 'o', 'p', |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_ARRAY(nlWeaveTLV_TAG_CONTEXT_SPECIFIC(kSampleEventTag_Samples)), |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER, |
| nlWeaveTLV_END_OF_CONTAINER |
| }; |
| |
| static void CheckSchemaGeneratedLogging(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid1, eid2; |
| WEAVE_ERROR err; |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| nl::Weave::Profiles::DataManagement::SampleTrait::Event ev; |
| nl::Weave::Profiles::DataManagement::OpenCloseTrait::Event ev2; |
| nl::StructureSchemaPointerPair appData; |
| nl::Weave::TLV::TLVWriter outer, writer; |
| uint8_t sBuffer[256]; |
| |
| InitializeEventLogging(context); |
| |
| uint32_t samples[6] = { 0, 1, 2, 3, 4, 5 }; |
| ev.state = 5; |
| ev.timestamp = 328; |
| ev.structure.a = true; |
| ev.structure.b.str = "bloopbloop\0"; |
| ev.samples.num_samples = 6; |
| ev.samples.samples_buf = samples; |
| |
| appData.mStructureData = static_cast<void *>(&ev); |
| appData.mFieldSchema = &sampleEventSchema; |
| |
| outer.Init(sBuffer, sizeof(sBuffer)); |
| |
| err = outer.OpenContainer(ProfileTag(0x0A00, 1), kTLVType_Structure, writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = SerializedDataToTLVWriterHelper(writer, kTag_EventData, &appData); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.CloseContainer(writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| // Verify the encoding |
| |
| NL_TEST_ASSERT(inSuite, outer.GetLengthWritten() == sizeof(SampleEventEncoding)); |
| NL_TEST_ASSERT(inSuite, memcmp(sBuffer, SampleEventEncoding, sizeof(SampleEventEncoding)) == 0); |
| |
| eid1 = LogSampleEvent(&ev, nl::Weave::Profiles::DataManagement::Production); |
| CheckLogState(inSuite, context, logMgmt, 1); |
| |
| ev2.state = 1; |
| eid2 = LogOpenCloseEvent(&ev2, nl::Weave::Profiles::DataManagement::Production); |
| CheckLogState(inSuite, context, logMgmt, 2); |
| |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid1, 2); |
| CheckLogReadOut(inSuite, context, logMgmt, nl::Weave::Profiles::DataManagement::Production, eid2, 1); |
| |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| static void CheckByteStringFieldType(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| event_id_t eventId; |
| ByteStringTestTrait::Event ev, deserializedEv; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| TLVReader testReader; |
| uint8_t buf[10]; |
| ev.byte_string.mLen = sizeof(buf); |
| ev.byte_string.mBuf = buf; |
| memset(buf, 0xaa, 10); |
| |
| InitializeEventLogging(context); |
| |
| eventId = LogByteStringTestEvent(&ev); |
| |
| err = FetchEventsHelper(testReader, eventId, gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = DeserializeByteStringTestEvent(testReader, &deserializedEv, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.byte_string.mLen == ev.byte_string.mLen); |
| NL_TEST_ASSERT(inSuite, memcmp(deserializedEv.byte_string.mBuf, ev.byte_string.mBuf, ev.byte_string.mLen) == 0); |
| } |
| |
| static void CheckByteStringArray(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| event_id_t eventId; |
| ByteStringArrayTestTrait::Event ev, deserializedEv; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| TLVReader testReader; |
| nl::SerializedByteString bytestrings[5]; |
| uint8_t buf[100]; |
| int i; |
| |
| // some magic numbers to initialize some varied byte strings |
| for (i = 0; i < 5; i++) |
| { |
| memset(&buf[i*5], (i+1)*40, (i+1)*5); |
| bytestrings[i].mLen = (i+1)*5; |
| bytestrings[i].mBuf = &buf[i*5]; |
| } |
| ev.testArray.num = 5; |
| ev.testArray.buf = bytestrings; |
| |
| InitializeEventLogging(context); |
| |
| eventId = LogByteStringArrayTestEvent(&ev); |
| |
| err = FetchEventsHelper(testReader, eventId, gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = DeserializeByteStringArrayTestEvent(testReader, &deserializedEv, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.testArray.num == ev.testArray.num); |
| for (i = 0; i < 5; i++) |
| { |
| NL_TEST_ASSERT(inSuite, deserializedEv.testArray.buf[i].mLen == ev.testArray.buf[i].mLen); |
| NL_TEST_ASSERT(inSuite, memcmp(deserializedEv.testArray.buf[i].mBuf, ev.testArray.buf[i].mBuf, ev.testArray.buf[i].mLen) == 0); |
| } |
| } |
| |
| struct DebugLogContext |
| { |
| const char *mRegion; |
| const char *mFmt; |
| va_list mArgs; |
| }; |
| |
| static event_id_t FastLogFreeform(ImportanceType inImportance, timestamp_t inTimestamp, const char * inFormat, ...) |
| { |
| DebugLogContext context; |
| nl::Weave::Profiles::DataManagement::EventOptions options; |
| event_id_t eid; |
| EventSchema schema = { |
| kWeaveProfile_NestDebug, |
| kNestDebug_StringLogEntryEvent, |
| inImportance, |
| 1, |
| 1 |
| }; |
| |
| va_start(context.mArgs, inFormat); |
| context.mRegion = ""; |
| context.mFmt = inFormat; |
| |
| options = EventOptions(inTimestamp, NULL, 0, nl::Weave::Profiles::DataManagement::kImportanceType_Invalid, false); |
| |
| eid = LogEvent(schema, PlainTextWriter, &context, &options); |
| |
| va_end(context.mArgs); |
| |
| return eid; |
| } |
| |
| static void CheckEvict(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid_prev, eid; |
| size_t counter = 0; |
| timestamp_t now; |
| InitializeEventLogging(context); |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| eid_prev = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| now += 10; |
| for (counter = 0; counter < 100; counter++) { |
| // Sample production events, spaced 10 milliseconds apart |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| now +=10; |
| |
| NL_TEST_ASSERT(inSuite, eid > 0); |
| NL_TEST_ASSERT(inSuite, eid == (eid_prev+1)); |
| |
| eid_prev = eid; |
| } |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| static WEAVE_ERROR ReadFirstEventHeader(TLVReader &aReader, timestamp_t &aTimestamp, utc_timestamp_t &aUtcTimestamp, event_id_t &aEventId) |
| { |
| WEAVE_ERROR err; |
| TLVType readerType; |
| uint64_t currentContextTag; |
| |
| err = aReader.Next(); |
| SuccessOrExit(err); |
| |
| err = aReader.EnterContainer(readerType); |
| SuccessOrExit(err); |
| |
| currentContextTag = aReader.GetTag(); |
| |
| while ((currentContextTag != ContextTag(kTag_EventData)) && !err) |
| { |
| if (currentContextTag == ContextTag(nl::Weave::Profiles::DataManagement::kTag_EventSystemTimestamp)) |
| { |
| err = aReader.Get(aTimestamp); |
| SuccessOrExit(err); |
| } |
| |
| if (currentContextTag == ContextTag(nl::Weave::Profiles::DataManagement::kTag_EventUTCTimestamp)) |
| { |
| err = aReader.Get(aUtcTimestamp); |
| SuccessOrExit(err); |
| } |
| |
| if (currentContextTag == ContextTag(nl::Weave::Profiles::DataManagement::kTag_EventID)) |
| { |
| err = aReader.Get(aEventId); |
| SuccessOrExit(err); |
| } |
| |
| err = aReader.Next(); |
| SuccessOrExit(err); |
| |
| currentContextTag = aReader.GetTag(); |
| } |
| |
| err = aReader.ExitContainer(readerType); |
| |
| exit: |
| return err; |
| } |
| |
| static void CheckFetchTimestamps(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid_prev, eid, event_id_read; |
| size_t counter = 0; |
| const int k_num_events = 10; |
| timestamp_t now; |
| utc_timestamp_t test_start; |
| InitializeEventLogging(context); |
| |
| test_start = static_cast<utc_timestamp_t>(System::Timer::GetCurrentEpoch()); |
| now = static_cast<timestamp_t>(test_start); |
| nl::Weave::Platform::Time::SetSystemTime(0); |
| |
| eid_prev = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "%u", now); |
| eid_prev = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Info, |
| now, |
| "%u", now); |
| now += 10; |
| for (counter = 1; counter < k_num_events; counter++) { |
| // Sample production events, spaced 10 milliseconds apart |
| if (counter == k_num_events/2) |
| { |
| nl::Weave::Platform::Time::SetSystemTime((test_start)*1000); |
| } |
| |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Info, |
| now, |
| "%u", now); |
| NL_TEST_ASSERT(inSuite, eid > 0); |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "%u", now); |
| |
| NL_TEST_ASSERT(inSuite, eid > 0); |
| NL_TEST_ASSERT(inSuite, eid == (eid_prev+1)); |
| |
| now += 10; |
| eid_prev = eid; |
| } |
| |
| NL_TEST_ASSERT(inSuite, eid_prev == k_num_events - 1); |
| |
| for (counter = 0; counter <= eid_prev; counter++) |
| { |
| TLVReader testReader; |
| TLVWriter testWriter; |
| utc_timestamp_t testUtcTimestamp = 0; |
| timestamp_t testTimestamp = 0; |
| event_id_t testEventID = 0; |
| |
| event_id_read = counter; |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Info, event_id_read); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| NL_TEST_ASSERT(inSuite, event_id_read == eid_prev + 1); |
| |
| if (context->mVerbose) |
| { |
| TLVReader reader; |
| reader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| |
| nl::Weave::TLV::Debug::Dump(reader, SimpleDumpWriter); |
| } |
| |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| |
| err = ReadFirstEventHeader(testReader, testTimestamp, testUtcTimestamp, testEventID); |
| NL_TEST_ASSERT(inSuite, testEventID == counter); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| #if WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS |
| if (counter >= k_num_events/2) |
| { |
| NL_TEST_ASSERT(inSuite, testUtcTimestamp == test_start + (testEventID) * 10); |
| } |
| else |
| #endif // WEAVE_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS |
| { |
| NL_TEST_ASSERT(inSuite, testTimestamp == static_cast<timestamp_t>(test_start) + (testEventID) * 10); |
| } |
| } |
| } |
| |
| WEAVE_ERROR WriteLargeEvent(nl::Weave::TLV::TLVWriter & writer, uint8_t inDataTag, void * anAppState) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| nl::Weave::TLV::TLVType containerType; |
| uint32_t *payloadEventSize; |
| uint8_t *dummyPayload = NULL; |
| |
| VerifyOrExit(anAppState != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| payloadEventSize = static_cast<uint32_t *>(anAppState); |
| |
| dummyPayload = reinterpret_cast<uint8_t*>(malloc(*payloadEventSize)); |
| VerifyOrExit(dummyPayload != NULL, err = WEAVE_ERROR_NO_MEMORY); |
| |
| memset(dummyPayload, 0xa5, *payloadEventSize); |
| |
| err = writer.StartContainer(ContextTag(nl::Weave::Profiles::DataManagement::kTag_EventData), nl::Weave::TLV::kTLVType_Structure, containerType); |
| SuccessOrExit(err); |
| |
| err = writer.PutBytes(nl::Weave::TLV::ContextTag(1), dummyPayload, *payloadEventSize); |
| SuccessOrExit(err); |
| |
| err = writer.EndContainer(containerType); |
| SuccessOrExit(err); |
| |
| err = writer.Finalize(); |
| |
| exit: |
| if (dummyPayload != NULL) |
| { |
| free(dummyPayload); |
| } |
| return err; |
| } |
| |
| static void CheckLargeEvents(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| uint32_t payloadSize; |
| event_id_t eid1, eid2, eid3, eid4; |
| EventSchema schema = { |
| OpenCloseProfileID, |
| 1, // Event type 1 |
| nl::Weave::Profiles::DataManagement::Production, |
| 1, |
| 1 |
| }; |
| |
| InitializeEventLogging(context); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| // we expect this payload to succeed |
| payloadSize = EVENT_PAYLOAD_SIZE_1; |
| eid1 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteLargeEvent, |
| static_cast<void*> (&payloadSize) |
| ); |
| NL_TEST_ASSERT(inSuite, eid1 == 0); |
| |
| eid2 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteLargeEvent, |
| static_cast<void*> (&payloadSize) |
| ); |
| NL_TEST_ASSERT(inSuite, eid2 == 1); |
| CheckLogState(inSuite, context, logMgmt, 2); |
| |
| // new test case - events will get retried if they fail |
| payloadSize = EVENT_PAYLOAD_SIZE_2; |
| eid3 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteLargeEvent, |
| static_cast<void*> (&payloadSize) |
| ); |
| NL_TEST_ASSERT(inSuite, eid3 == 2); |
| |
| // this event is wider than the debug buffer |
| payloadSize = EVENT_PAYLOAD_SIZE_3; |
| eid4 = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteLargeEvent, |
| static_cast<void*> (&payloadSize) |
| ); |
| NL_TEST_ASSERT(inSuite, eid4 == 0); |
| } |
| |
| static void CheckDropEvents(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| int counter = 0; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| EventSchema schema = { |
| OpenCloseProfileID, |
| 1, // Event type 1 |
| nl::Weave::Profiles::DataManagement::Production, |
| 1, |
| 1 |
| }; |
| event_id_t eid_prev, eid; |
| CircularEventBuffer *prodBuf = reinterpret_cast<CircularEventBuffer *>(&gProdEventBuffer[0]); |
| uint32_t eventSizes[] = { |
| EVENT_ENVELOPE_SIZE, |
| EVENT_PAYLOAD_SIZE_1, |
| EVENT_PAYLOAD_SIZE_2, |
| }; |
| const uint32_t numSizes = sizeof(eventSizes)/sizeof(uint32_t); |
| TLVWriter testWriter; |
| |
| InitializeEventLogging(context); |
| |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logMgmt = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| // register some fake events |
| err = LogMockExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| eid_prev = prodBuf->mLastEventID; |
| |
| while (prodBuf->mFirstEventID <= 10) |
| { |
| eid = nl::Weave::Profiles::DataManagement::LogEvent( |
| schema, |
| WriteLargeEvent, |
| static_cast<void*> (&eventSizes[counter++ % numSizes]) |
| ); |
| NL_TEST_ASSERT(inSuite, eid > eid_prev); |
| |
| if (eid_prev >= 10) |
| { |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = logMgmt.FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid_prev); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| NL_TEST_ASSERT(inSuite, eid_prev == eid + 1); |
| } |
| |
| eid_prev = eid; |
| } |
| |
| { |
| TLVReader testReader; |
| event_id_t testEventID, eid_in = 0; |
| timestamp_t testTimestamp; |
| utc_timestamp_t testUtcTimestamp; |
| |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = logMgmt.FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid_in); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| NL_TEST_ASSERT(inSuite, eid_in > 10); |
| |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| err = ReadFirstEventHeader(testReader, testTimestamp, testUtcTimestamp, testEventID); |
| NL_TEST_ASSERT(inSuite, testEventID >= 10); |
| } |
| } |
| |
| static void CheckFetchEvents(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| event_id_t eid_prev, eid, eventId; |
| size_t counter = 0; |
| // small buffer, sized s.t. the events generated below will be |
| // larger than a single buffer, but smaller than two buffers. |
| uint8_t smallMemoryBackingStore[1280]; |
| PacketBuffer *pbuf = PacketBuffer::New(); |
| TLVWriter testWriter; |
| WEAVE_ERROR err; |
| timestamp_t now; |
| InitializeEventLogging(context); |
| now = static_cast<timestamp_t>(0); |
| |
| eid_prev = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| |
| // The magic number "40" below is selected to be large enough to |
| // generate more events than can fit in a single PacketBuffer, but |
| // fewer than can fit in 2 packet buffers. This ensures that we |
| // test both the cases when we run out of log before ending the |
| // buffer, and the cases when the writer runs out of space before |
| // the end of the log. |
| now += 10; |
| for (counter = 0; counter < 40; counter++) { |
| // Sample production events, spaced 10 milliseconds apart |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| now += 10; |
| |
| NL_TEST_ASSERT(inSuite, eid > 0); |
| NL_TEST_ASSERT(inSuite, eid == (eid_prev+1)); |
| |
| eid_prev = eid; |
| } |
| |
| if (context->mVerbose) |
| { |
| PrintEventLog(); |
| } |
| |
| // Test that offloading events into large buffer completes and |
| // returns WEAVE_END_OF_TLV |
| eventId = 0; |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| |
| // Test that offloading events into a smaller buffer with bounded |
| // write length results in WEAVE_ERROR_BUFFER_TOO_SMALL and the |
| // correct number of events as indicated by eventId |
| |
| eventId = 0; |
| eid_prev = eventId; |
| testWriter.Init(smallMemoryBackingStore, sizeof(smallMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_BUFFER_TOO_SMALL); |
| { |
| TLVReader reader; |
| size_t eventCount; |
| reader.Init(smallMemoryBackingStore, testWriter.GetLengthWritten()); |
| |
| err = nl::Weave::TLV::Utilities::Count(reader, eventCount, false); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| NL_TEST_ASSERT(inSuite, eventId - eid_prev == eventCount); |
| } |
| |
| // resume event offload; this one should reach the end of the |
| // log (by construction) |
| testWriter.Init(smallMemoryBackingStore, sizeof(smallMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| |
| // Test that offloading events into a PacketBuffer-backed writer with the default (unbounded) max write length results in WEAVE_ERROR_NO_MEMORY |
| eventId = 0; |
| testWriter.Init(pbuf); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_NO_MEMORY); |
| |
| PacketBuffer::Free(pbuf); |
| pbuf = PacketBuffer::New(); |
| testWriter.Init(pbuf); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eventId); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| |
| if (context->bdx) |
| { |
| DoBDXUpload(context); |
| } |
| } |
| |
| static void CheckBasicEventDeserialization(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| |
| nl::Weave::Profiles::DataManagement::SampleTrait::Event ev, ev2; |
| nl::StructureSchemaPointerPair appData; |
| nl::Weave::TLV::TLVWriter outer, writer; |
| nl::Weave::TLV::TLVReader reader, outerReader; |
| uint8_t sBuffer[256]; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| InitializeEventLogging(context); |
| |
| uint32_t samples[6] = { 0, 1, 2, 3, 4, 5 }; |
| ev.state = 5; |
| ev.timestamp = 328; |
| ev.structure.a = true; |
| ev.structure.b.str = "bloopbloop\0"; |
| ev.samples.num_samples = 6; |
| ev.samples.samples_buf = samples; |
| |
| appData.mStructureData = static_cast<void *>(&ev); |
| appData.mFieldSchema = &sampleEventSchema; |
| |
| outer.Init(sBuffer, sizeof(sBuffer)); |
| |
| err = outer.OpenContainer(ProfileTag(0x0A00, 1), kTLVType_Structure, writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = SerializedDataToTLVWriterHelper(writer, kTag_EventData, &appData); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.CloseContainer(writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // Verify the encoding |
| |
| NL_TEST_ASSERT(inSuite, outer.GetLengthWritten() == sizeof(SampleEventEncoding)); |
| NL_TEST_ASSERT(inSuite, memcmp(sBuffer, SampleEventEncoding, sizeof(SampleEventEncoding)) == 0); |
| |
| // Now de-serialize. |
| |
| outerReader.Init(sBuffer, outer.GetLengthWritten()); |
| err = outerReader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| appData.mStructureData = static_cast<void *>(&ev2); |
| appData.mFieldSchema = &sampleEventSchema; |
| |
| err = outerReader.OpenContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = reader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::Weave::Profiles::DataManagement::DeserializeSampleEvent(reader, &ev2, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outerReader.CloseContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, ev2.state == ev.state); |
| NL_TEST_ASSERT(inSuite, ev2.timestamp == ev.timestamp); |
| NL_TEST_ASSERT(inSuite, ev2.structure.a == ev.structure.a); |
| NL_TEST_ASSERT(inSuite, strcmp(ev2.structure.b.str, ev.structure.b.str) == 0); |
| NL_TEST_ASSERT(inSuite, ev2.samples.num_samples == ev.samples.num_samples); |
| for (uint32_t i = 0; i < ev2.samples.num_samples; i++) |
| { |
| NL_TEST_ASSERT(inSuite, ev2.samples.samples_buf[i] == ev.samples.samples_buf[i]); |
| } |
| |
| nl::DeallocateDeserializedStructure(&ev2, &sampleEventSchema, &serializationContext); |
| } |
| |
| static void CheckComplexEventDeserialization(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| |
| Schema::Nest::Test::Trait::TestETrait::TestEEvent ev = { 0 }; |
| Schema::Nest::Test::Trait::TestETrait::TestEEvent ev2 = { 0 }; |
| nl::StructureSchemaPointerPair appData; |
| nl::Weave::TLV::TLVWriter outer, writer; |
| nl::Weave::TLV::TLVReader reader, outerReader; |
| uint8_t sBuffer[512]; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| InitializeEventLogging(context); |
| |
| memset(&ev, 0, sizeof(ev)); |
| |
| uint32_t numbaz[5]; |
| numbaz[0] = 1; |
| numbaz[1] = 3; |
| numbaz[2] = 5; |
| numbaz[3] = 7; |
| numbaz[4] = 10; |
| Schema::Nest::Test::Trait::TestCommonTrait::CommonStructE strukchaz[3]; |
| strukchaz[0].seA = 1111111; |
| strukchaz[0].seB = true; |
| strukchaz[1].seA = 2222222; |
| strukchaz[1].seB = false; |
| strukchaz[2].seA = 3333333; |
| strukchaz[2].seB = true; |
| ev.teA = 444444; |
| ev.teB = -555555; |
| ev.teC = true; |
| ev.teD = -666666; |
| ev.teE.seA = 777777; |
| ev.teE.seB = false; |
| ev.teE.seC = -888888; |
| ev.teF = 999999; |
| ev.teG.seA = 101010; |
| ev.teG.seB = true; |
| ev.teH.num = sizeof(numbaz)/sizeof(numbaz[0]); |
| ev.teH.buf = numbaz; |
| ev.teI.num = sizeof(strukchaz)/sizeof(strukchaz[0]); |
| ev.teI.buf = strukchaz; |
| ev.teJ = 12121; |
| |
| appData.mStructureData = static_cast<void *>(&ev); |
| appData.mFieldSchema = &Schema::Nest::Test::Trait::TestETrait::TestEEvent::FieldSchema; |
| |
| outer.Init(sBuffer, sizeof(sBuffer)); |
| |
| err = outer.OpenContainer(ProfileTag(0x0A00, 1), kTLVType_Structure, writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = SerializedDataToTLVWriterHelper(writer, kTag_EventData, &appData); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.CloseContainer(writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // Now de-serialize. |
| |
| outerReader.Init(sBuffer, outer.GetLengthWritten()); |
| |
| err = outerReader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| appData.mStructureData = static_cast<void *>(&ev2); |
| appData.mFieldSchema = &Schema::Nest::Test::Trait::TestETrait::TestEEvent::FieldSchema; |
| |
| err = outerReader.OpenContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = reader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::DeserializeEvent(reader, &ev2, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| SuccessOrExit(err); |
| |
| err = outerReader.CloseContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, ev2.teA == ev.teA); |
| NL_TEST_ASSERT(inSuite, ev2.teB == ev.teB); |
| NL_TEST_ASSERT(inSuite, ev2.teC == ev.teC); |
| NL_TEST_ASSERT(inSuite, ev2.teD == ev.teD); |
| NL_TEST_ASSERT(inSuite, ev2.teE.seA == ev.teE.seA); |
| NL_TEST_ASSERT(inSuite, ev2.teE.seB == ev.teE.seB); |
| NL_TEST_ASSERT(inSuite, ev2.teE.seC == ev.teE.seC); |
| NL_TEST_ASSERT(inSuite, ev2.teF == ev.teF); |
| NL_TEST_ASSERT(inSuite, ev2.teG.seA == ev.teG.seA); |
| NL_TEST_ASSERT(inSuite, ev2.teG.seB == ev.teG.seB); |
| for (uint32_t i = 0; i < ev2.teH.num; i++) |
| { |
| NL_TEST_ASSERT(inSuite, ev2.teH.buf[i] == ev.teH.buf[i]); |
| } |
| for (uint32_t i = 0; i < ev2.teI.num; i++) |
| { |
| NL_TEST_ASSERT(inSuite, ev2.teI.buf[i].seA == ev.teI.buf[i].seA); |
| NL_TEST_ASSERT(inSuite, ev2.teI.buf[i].seB == ev.teI.buf[i].seB); |
| } |
| NL_TEST_ASSERT(inSuite, ev2.IsTeJPresent()); |
| NL_TEST_ASSERT(inSuite, ev2.teJ == ev.teJ); |
| |
| nl::DeallocateEvent(&ev2, &serializationContext); |
| |
| exit: |
| return; |
| } |
| |
| static void CheckEmptyArrayEventDeserialization(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| |
| nl::Weave::Profiles::DataManagement::SampleTrait::Event ev, ev2; |
| nl::StructureSchemaPointerPair appData; |
| nl::Weave::TLV::TLVWriter outer, writer; |
| nl::Weave::TLV::TLVReader reader, outerReader; |
| uint8_t sBuffer[256]; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| InitializeEventLogging(context); |
| |
| ev.state = 5; |
| ev.timestamp = 328; |
| ev.structure.a = true; |
| ev.structure.b.str = "bloopbloop\0"; |
| ev.samples.num_samples = 0; |
| ev.samples.samples_buf = NULL; |
| |
| appData.mStructureData = static_cast<void *>(&ev); |
| appData.mFieldSchema = &sampleEventSchema; |
| |
| outer.Init(sBuffer, sizeof(sBuffer)); |
| |
| err = outer.OpenContainer(ProfileTag(0x0A00, 1), kTLVType_Structure, writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = SerializedDataToTLVWriterHelper(writer, kTag_EventData, &appData); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = writer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.CloseContainer(writer); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outer.Finalize(); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| // Verify the encoding |
| |
| NL_TEST_ASSERT(inSuite, outer.GetLengthWritten() == sizeof(SampleEmptyArrayEventEncoding)); |
| NL_TEST_ASSERT(inSuite, memcmp(sBuffer, SampleEmptyArrayEventEncoding, sizeof(SampleEmptyArrayEventEncoding)) == 0); |
| |
| // Now de-serialize. |
| |
| outerReader.Init(sBuffer, outer.GetLengthWritten()); |
| |
| err = outerReader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| appData.mStructureData = static_cast<void *>(&ev2); |
| appData.mFieldSchema = &sampleEventSchema; |
| |
| err = outerReader.OpenContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = reader.Next(); // Positions us at the beginning of the first element. |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::Weave::Profiles::DataManagement::DeserializeSampleEvent(reader, &ev2, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = outerReader.CloseContainer(reader); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, ev2.state == ev.state); |
| NL_TEST_ASSERT(inSuite, ev2.timestamp == ev.timestamp); |
| NL_TEST_ASSERT(inSuite, ev2.structure.a == ev.structure.a); |
| NL_TEST_ASSERT(inSuite, strcmp(ev2.structure.b.str, ev.structure.b.str) == 0); |
| NL_TEST_ASSERT(inSuite, ev2.samples.num_samples == ev.samples.num_samples); |
| NL_TEST_ASSERT(inSuite, ev2.samples.samples_buf == NULL); |
| |
| memMgmt.mem_free((void *)ev2.structure.b.str); |
| } |
| |
| static WEAVE_ERROR FetchEventsHelper(TLVReader &aReader, event_id_t aEventId, uint8_t *aBackingStore, size_t aLen, ImportanceType aImportance) |
| { |
| WEAVE_ERROR err; |
| TLVWriter testWriter; |
| TLVType readerType; |
| |
| testWriter.Init(aBackingStore, aLen); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, aImportance, aEventId); |
| VerifyOrExit(err == WEAVE_END_OF_TLV, err = WEAVE_ERROR_INCORRECT_STATE); |
| |
| aReader.Init(aBackingStore, testWriter.GetLengthWritten()); |
| |
| err = aReader.Next(); |
| SuccessOrExit(err); |
| |
| err = aReader.EnterContainer(readerType); |
| SuccessOrExit(err); |
| |
| while ((aReader.GetTag() != ContextTag(kTag_EventData)) && (err == WEAVE_NO_ERROR)) |
| { |
| err = aReader.Next(); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| class TestEventProcessor : public EventProcessor { |
| public: |
| TestEventProcessor(); |
| WEAVE_ERROR ProcessEvent(TLVReader inReader, SubscriptionClient &inClient, const EventHeader &inEventHeader); |
| WEAVE_ERROR GapDetected(const EventHeader &inEventHeader); |
| |
| SchemaVersionRange mSchemaVersionRange; |
| }; |
| |
| TestEventProcessor::TestEventProcessor() |
| : EventProcessor(0) |
| { |
| } |
| |
| WEAVE_ERROR TestEventProcessor::ProcessEvent(TLVReader inReader, SubscriptionClient &inClient, const EventHeader &inEventHeader) |
| { |
| mSchemaVersionRange = inEventHeader.mDataSchemaVersionRange; |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR TestEventProcessor::GapDetected(const EventHeader &inEventHeader) |
| { |
| return WEAVE_NO_ERROR; |
| } |
| |
| static WEAVE_ERROR VersionCompatibilityHelper(void *inContext, SchemaVersionRange &encodedSchemaVersionRange, SchemaVersionRange &decodedSchemaVersionRange) |
| { |
| WEAVE_ERROR err; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| |
| TLVReader testReader; |
| uint8_t backingStore[1024]; |
| uint32_t bytesWritten; |
| Schema::Nest::Test::Trait::TestETrait::TestEEvent evN = { 0 }; |
| EventSchema testSchema = Schema::Nest::Test::Trait::TestETrait::TestEEvent::Schema; |
| TestEventProcessor eventProcessor; |
| |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| nl::StructureSchemaPointerPair appData; |
| |
| PrepareBinding(context); |
| InitSubscriptionClient(context); |
| |
| testSchema.mMinCompatibleDataSchemaVersion = encodedSchemaVersionRange.mMinVersion; |
| testSchema.mDataSchemaVersion = encodedSchemaVersionRange.mMaxVersion; |
| |
| appData.mStructureData = static_cast<void *>(&evN); |
| appData.mFieldSchema = &Schema::Nest::Test::Trait::TestETrait::TestEEvent::FieldSchema; |
| |
| event_id_t eventId = nl::Weave::Profiles::DataManagement::LogEvent(testSchema, nl::SerializedDataToTLVWriterHelper, (void *)&appData); |
| |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore)); |
| SuccessOrExit(err); |
| |
| bytesWritten = testReader.GetRemainingLength() + testReader.GetLengthRead(); |
| testReader.Init(backingStore, bytesWritten); |
| |
| err = eventProcessor.ProcessEvents(testReader, *context->mSubClient); |
| SuccessOrExit(err); |
| |
| decodedSchemaVersionRange = eventProcessor.mSchemaVersionRange; |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| exit: |
| return err; |
| } |
| |
| static void CheckVersion1DataCompatibility(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| SchemaVersionRange encodedSchemaVersionRange, decodedSchemaVersionRange; |
| |
| encodedSchemaVersionRange.mMaxVersion = 1; |
| encodedSchemaVersionRange.mMinVersion = 1; |
| |
| err = VersionCompatibilityHelper(inContext, encodedSchemaVersionRange, decodedSchemaVersionRange); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| NL_TEST_ASSERT(inSuite, encodedSchemaVersionRange == decodedSchemaVersionRange); |
| } |
| |
| static void CheckForwardDataCompatibility(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| SchemaVersionRange encodedSchemaVersionRange, decodedSchemaVersionRange; |
| |
| encodedSchemaVersionRange.mMaxVersion = 4; |
| encodedSchemaVersionRange.mMinVersion = 1; |
| |
| err = VersionCompatibilityHelper(inContext, encodedSchemaVersionRange, decodedSchemaVersionRange); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| NL_TEST_ASSERT(inSuite, encodedSchemaVersionRange == decodedSchemaVersionRange); |
| } |
| |
| static void CheckDataIncompatibility(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err; |
| SchemaVersionRange encodedSchemaVersionRange, decodedSchemaVersionRange; |
| |
| encodedSchemaVersionRange.mMaxVersion = 4; |
| encodedSchemaVersionRange.mMinVersion = 2; |
| |
| err = VersionCompatibilityHelper(inContext, encodedSchemaVersionRange, decodedSchemaVersionRange); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| NL_TEST_ASSERT(inSuite, encodedSchemaVersionRange == decodedSchemaVersionRange); |
| } |
| |
| static void CheckNullableFieldsSimple(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| |
| TLVReader testReader; |
| uint8_t backingStore[1024]; |
| Schema::Nest::Test::Trait::TestETrait::TestEEvent evN = { 0 }; |
| Schema::Nest::Test::Trait::TestETrait::TestEEvent deserializedEvN = { 0 }; |
| |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| InitializeEventLogging(context); |
| |
| evN.teA = 10; |
| evN.SetTeJNull(); |
| |
| event_id_t eventId = nl::LogEvent(&evN); |
| |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| err = nl::DeserializeEvent(testReader, &deserializedEvN, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEvN.teA == evN.teA); |
| NL_TEST_ASSERT(inSuite, GET_FIELD_NULLIFIED_BIT(deserializedEvN.__nullified_fields__, 0)); |
| NL_TEST_ASSERT(inSuite, deserializedEvN.IsTeJPresent() == false); |
| } |
| |
| static void CheckNullableFieldsComplex(nlTestSuite *inSuite, void *inContext) |
| { |
| // pattern: for each bit in nullified fields, set and check |
| // for array of nullable structs, set and check |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| |
| uint8_t backingStore[1024]; |
| Schema::Nest::Test::Trait::TestETrait::TestENullableEvent teN_s = { 0 }; |
| |
| teN_s.neA = 0xAAAAAAAA; |
| teN_s.neB = -1; |
| teN_s.neC = true; |
| teN_s.neD = "bar\0"; |
| teN_s.neE = 5; |
| teN_s.neF = 0x77777777; |
| teN_s.neG = -30; |
| teN_s.neH = false; |
| teN_s.neI = "foo\0"; |
| teN_s.neJ.neA = 88; |
| teN_s.neJ.neB = true; |
| |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| |
| InitializeEventLogging(context); |
| |
| // hardcoded number nullable fields |
| for (int i = 0; i < 10; i++) |
| { |
| Schema::Nest::Test::Trait::TestETrait::TestENullableEvent teN_d = { 0 }; |
| event_id_t eventId; |
| TLVReader testReader; |
| |
| memset(teN_s.__nullified_fields__, 0, sizeof(teN_s.__nullified_fields__)); |
| memset(teN_s.neJ.__nullified_fields__, 0, sizeof(teN_s.neJ.__nullified_fields__)); |
| SET_FIELD_NULLIFIED_BIT(teN_s.__nullified_fields__, i); |
| |
| eventId = nl::LogEvent(&teN_s); |
| |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::DeserializeEvent(testReader, &teN_d, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, GET_FIELD_NULLIFIED_BIT(teN_d.__nullified_fields__, i)); |
| |
| if (i != 0) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neA == teN_s.neA); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeAPresent() == false); |
| } |
| |
| if (i != 1) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neB == teN_s.neB); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeBPresent() == false); |
| } |
| |
| if (i != 2) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neC == teN_s.neC); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeCPresent() == false); |
| } |
| |
| if (i != 3) |
| { |
| NL_TEST_ASSERT(inSuite, strcmp(teN_d.neD, teN_s.neD) == 0); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeDPresent() == false); |
| } |
| |
| if (i != 4) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neE == teN_s.neE); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeEPresent() == false); |
| } |
| |
| if (i != 5) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neF == teN_s.neF); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeFPresent() == false); |
| } |
| |
| if (i != 6) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neG == teN_s.neG); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeGPresent() == false); |
| } |
| |
| if (i != 7) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neH == teN_s.neH); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeHPresent() == false); |
| } |
| |
| if (i != 8) |
| { |
| NL_TEST_ASSERT(inSuite, strcmp(teN_d.neI, teN_s.neI) == 0); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeIPresent() == false); |
| } |
| |
| if (i != 9) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.neA == teN_s.neJ.neA); |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.neB == teN_s.neJ.neB); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.IsNeJPresent() == false); |
| } |
| |
| err = nl::DeallocateEvent(&teN_d, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| } |
| |
| for (int i = 0; i < 2; i++) |
| { |
| Schema::Nest::Test::Trait::TestETrait::TestENullableEvent teN_d = { 0 }; |
| event_id_t eventId; |
| TLVReader testReader; |
| |
| memset(teN_s.__nullified_fields__, 0, sizeof(teN_s.__nullified_fields__)); |
| memset(teN_s.neJ.__nullified_fields__, 0, sizeof(teN_s.neJ.__nullified_fields__)); |
| SET_FIELD_NULLIFIED_BIT(teN_s.neJ.__nullified_fields__, i); |
| |
| eventId = nl::LogEvent(&teN_s); |
| |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = nl::DeserializeEvent(testReader, &teN_d, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, GET_FIELD_NULLIFIED_BIT(teN_d.neJ.__nullified_fields__, i)); |
| |
| NL_TEST_ASSERT(inSuite, teN_d.neA == teN_s.neA); |
| NL_TEST_ASSERT(inSuite, teN_d.neB == teN_s.neB); |
| NL_TEST_ASSERT(inSuite, teN_d.neC == teN_s.neC); |
| NL_TEST_ASSERT(inSuite, strcmp(teN_d.neD, teN_s.neD) == 0); |
| NL_TEST_ASSERT(inSuite, teN_d.neE == teN_s.neE); |
| NL_TEST_ASSERT(inSuite, teN_d.neF == teN_s.neF); |
| NL_TEST_ASSERT(inSuite, teN_d.neG == teN_s.neG); |
| NL_TEST_ASSERT(inSuite, teN_d.neH == teN_s.neH); |
| NL_TEST_ASSERT(inSuite, strcmp(teN_d.neI, teN_s.neI) == 0); |
| |
| if (i == 1) |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.neA == teN_s.neJ.neA); |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.IsNeBPresent() == false); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.neB == teN_s.neJ.neB); |
| NL_TEST_ASSERT(inSuite, teN_d.neJ.IsNeAPresent() == false); |
| } |
| } |
| } |
| |
| static void CheckWDMOffloadTrigger(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| timestamp_t now; |
| size_t counter = 0; |
| uint32_t eventSize; |
| ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler *testSubHandler; |
| ::nl::Weave::Profiles::DataManagement::SubscriptionHandler *subHandler; |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logger = |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| |
| event_id_t eid, eid_prev; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| |
| // Each event is about 40 bytes; write 40 of those to ensure we |
| // override the default WDM event byte threshold |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| eid_prev = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter++); |
| eventSize = logger.GetBytesWritten(); |
| |
| for (size_t expectedBufferSize = 0; expectedBufferSize < WEAVE_CONFIG_EVENT_LOGGING_BYTE_THRESHOLD; expectedBufferSize += eventSize) |
| { |
| now += 10; |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter++); |
| NL_TEST_ASSERT(inSuite, eid == (eid_prev + 1)); |
| eid_prev = eid; |
| } |
| |
| // subscription engine has no subscription handlers, we should not be running the WDM |
| NL_TEST_ASSERT(inSuite, logger.CheckShouldRunWDM() == false); |
| |
| // create a fake subscription, and start messing with it to check that WDM trigger will run |
| err = ::nl::Weave::Profiles::DataManagement::SubscriptionEngine::GetInstance()->NewSubscriptionHandler(&subHandler); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| testSubHandler = static_cast<::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler *>(subHandler); |
| new (testSubHandler) ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler(); |
| |
| NL_TEST_ASSERT(inSuite, testSubHandler->IsFree()); |
| |
| NL_TEST_ASSERT(inSuite, logger.CheckShouldRunWDM() == false); |
| |
| testSubHandler->SetActive(); |
| NL_TEST_ASSERT(inSuite, logger.CheckShouldRunWDM() == true); |
| |
| testSubHandler->SetEventLogEndpoint(logger); |
| NL_TEST_ASSERT(inSuite, logger.CheckShouldRunWDM() == false); |
| |
| // A single event at this point should not trigger the engine |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter++); |
| NL_TEST_ASSERT(inSuite, eid == (eid_prev + 1)); |
| NL_TEST_ASSERT(inSuite, logger.CheckShouldRunWDM() == false); |
| } |
| |
| |
| // Mock'd Events (would be autogen'd by phoenix) |
| struct CurrentEvent |
| { |
| int32_t enumState; |
| bool boolState; |
| static const nl::SchemaFieldDescriptor FieldSchema; |
| enum { kProfileId = 0x1U, kEventTypeId = 0x1U }; |
| static const nl::Weave::Profiles::DataManagement::EventSchema Schema; |
| }; |
| const nl::FieldDescriptor CurrentEventFieldDescriptors[] = |
| { |
| { NULL, offsetof(CurrentEvent, enumState), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 0), 1 }, |
| { NULL, offsetof(CurrentEvent, boolState), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeBoolean, 0), 32 }, |
| }; |
| const nl::SchemaFieldDescriptor CurrentEvent::FieldSchema = { .mNumFieldDescriptorElements = sizeof(CurrentEventFieldDescriptors)/sizeof(CurrentEventFieldDescriptors[0]), .mFields = CurrentEventFieldDescriptors, .mSize = sizeof(CurrentEvent) }; |
| const nl::Weave::Profiles::DataManagement::EventSchema CurrentEvent::Schema = { .mProfileId = kProfileId, .mStructureType = 0x1, .mImportance = nl::Weave::Profiles::DataManagement::ProductionCritical, .mDataSchemaVersion = 1, .mMinCompatibleDataSchemaVersion = 1 }; |
| |
| struct FutureEventNewBaseField |
| { |
| int32_t enumState; |
| int32_t otherEnumState; |
| bool boolState; |
| static const nl::SchemaFieldDescriptor FieldSchema; |
| enum { kProfileId = 0x1U, kEventTypeId = 0x1U }; |
| static const nl::Weave::Profiles::DataManagement::EventSchema Schema; |
| }; |
| const nl::FieldDescriptor FutureEventNewBaseFieldFieldDescriptors[] = |
| { |
| { NULL, offsetof(FutureEventNewBaseField, enumState), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 0), 1 }, |
| { NULL, offsetof(FutureEventNewBaseField, otherEnumState), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 0), 2 }, |
| { NULL, offsetof(FutureEventNewBaseField, boolState), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeBoolean, 0), 32 }, |
| }; |
| const nl::SchemaFieldDescriptor FutureEventNewBaseField::FieldSchema = { .mNumFieldDescriptorElements = sizeof(FutureEventNewBaseFieldFieldDescriptors)/sizeof(FutureEventNewBaseFieldFieldDescriptors[0]), .mFields = FutureEventNewBaseFieldFieldDescriptors, .mSize = sizeof(FutureEventNewBaseField) }; |
| const nl::Weave::Profiles::DataManagement::EventSchema FutureEventNewBaseField::Schema = { .mProfileId = kProfileId, .mStructureType = 0x1, .mImportance = nl::Weave::Profiles::DataManagement::ProductionCritical, .mDataSchemaVersion = 2, .mMinCompatibleDataSchemaVersion = 1 }; |
| |
| static void CheckDeserializingNewerVersion(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| uint8_t backingStore[1024]; |
| InitializeEventLogging(context); |
| |
| FutureEventNewBaseField externalEv = { 0 }; |
| externalEv.enumState = 10; |
| externalEv.otherEnumState = 20; |
| externalEv.boolState = true; |
| |
| event_id_t eventId = nl::LogEvent(&externalEv); |
| |
| TLVReader testReader; |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore), nl::Weave::Profiles::DataManagement::ProductionCritical); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| CurrentEvent deserializedEv = { 0 }; |
| nl::StructureSchemaPointerPair structureSchemaPair; |
| structureSchemaPair.mStructureData = &deserializedEv; |
| structureSchemaPair.mFieldSchema = &CurrentEvent::FieldSchema; |
| |
| err = nl::TLVReaderToDeserializedDataHelper(testReader, nl::Weave::Profiles::DataManagement::kTag_EventData, |
| (void *)&structureSchemaPair, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.enumState == externalEv.enumState); |
| NL_TEST_ASSERT(inSuite, deserializedEv.boolState == externalEv.boolState); |
| } |
| |
| static void CheckDeserializingOlderVersion(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| uint8_t backingStore[1024]; |
| InitializeEventLogging(context); |
| |
| CurrentEvent externalEv = { 0 }; |
| externalEv.enumState = 10; |
| externalEv.boolState = true; |
| |
| event_id_t eventId = nl::LogEvent(&externalEv); |
| |
| TLVReader testReader; |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore), nl::Weave::Profiles::DataManagement::ProductionCritical); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| FutureEventNewBaseField deserializedEv = { 0 }; |
| nl::StructureSchemaPointerPair structureSchemaPair; |
| structureSchemaPair.mStructureData = &deserializedEv; |
| structureSchemaPair.mFieldSchema = &FutureEventNewBaseField::FieldSchema; |
| |
| err = nl::TLVReaderToDeserializedDataHelper(testReader, nl::Weave::Profiles::DataManagement::kTag_EventData, |
| (void *)&structureSchemaPair, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.enumState == externalEv.enumState); |
| NL_TEST_ASSERT(inSuite, deserializedEv.otherEnumState == 0); |
| NL_TEST_ASSERT(inSuite, deserializedEv.boolState == externalEv.boolState); |
| } |
| |
| // --------------- |
| struct CurrentNullableEvent |
| { |
| int32_t baseEnum; |
| void SetBaseEnumNull(void); |
| void SetBaseEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsBaseEnumPresent(void); |
| #endif |
| |
| int32_t extendedEnum; |
| void SetExtendedEnumNull(void); |
| void SetExtendedEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsExtendedEnumPresent(void); |
| #endif |
| uint8_t __nullified_fields__[2 /8 + 1]; |
| static const nl::SchemaFieldDescriptor FieldSchema; |
| enum { kProfileId = 0x1U, kEventTypeId = 0x1U }; |
| static const nl::Weave::Profiles::DataManagement::EventSchema Schema; |
| }; |
| const nl::FieldDescriptor CurrentNullableEventFieldDescriptors[] = |
| { |
| { NULL, offsetof(CurrentNullableEvent, baseEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 1 }, |
| { NULL, offsetof(CurrentNullableEvent, extendedEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 32 }, |
| }; |
| const nl::SchemaFieldDescriptor CurrentNullableEvent::FieldSchema = { .mNumFieldDescriptorElements = sizeof(CurrentNullableEventFieldDescriptors)/sizeof(CurrentNullableEventFieldDescriptors[0]), .mFields = CurrentNullableEventFieldDescriptors, .mSize = sizeof(CurrentNullableEvent) }; |
| const nl::Weave::Profiles::DataManagement::EventSchema CurrentNullableEvent::Schema = { .mProfileId = kProfileId, .mStructureType = 0x1, .mImportance = nl::Weave::Profiles::DataManagement::ProductionCritical, .mDataSchemaVersion = 2, .mMinCompatibleDataSchemaVersion = 1 }; |
| inline void CurrentNullableEvent::SetBaseEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 0); } |
| inline void CurrentNullableEvent::SetBaseEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 0); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool CurrentNullableEvent::IsBaseEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 0)); } |
| #endif |
| inline void CurrentNullableEvent::SetExtendedEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 1); } |
| inline void CurrentNullableEvent::SetExtendedEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 1); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool CurrentNullableEvent::IsExtendedEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 1)); } |
| #endif |
| |
| struct FutureNullableEvent |
| { |
| int32_t baseEnum; |
| void SetBaseEnumNull(void); |
| void SetBaseEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsBaseEnumPresent(void); |
| #endif |
| |
| int32_t futureEnum; |
| void SetFutureEnumNull(void); |
| void SetFutureEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsFutureEnumPresent(void); |
| #endif |
| |
| int32_t extendedEnum; |
| void SetExtendedEnumNull(void); |
| void SetExtendedEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsExtendedEnumPresent(void); |
| #endif |
| |
| int32_t futureExtendedEnum; |
| void SetFutureExtendedEnumNull(void); |
| void SetFutureExtendedEnumPresent(void); |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| bool IsFutureExtendedEnumPresent(void); |
| #endif |
| |
| uint8_t __nullified_fields__[4 /8 + 1]; |
| static const nl::SchemaFieldDescriptor FieldSchema; |
| enum { kProfileId = 0x1U, kEventTypeId = 0x1U }; |
| static const nl::Weave::Profiles::DataManagement::EventSchema Schema; |
| }; |
| const nl::FieldDescriptor FutureNullableEventFieldDescriptors[] = |
| { |
| { NULL, offsetof(FutureNullableEvent, baseEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 1 }, |
| { NULL, offsetof(FutureNullableEvent, futureEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 2 }, |
| { NULL, offsetof(FutureNullableEvent, extendedEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 32 }, |
| { NULL, offsetof(FutureNullableEvent, futureExtendedEnum), SET_TYPE_AND_FLAGS(nl::SerializedFieldTypeInt32, 1), 33 }, |
| }; |
| const nl::SchemaFieldDescriptor FutureNullableEvent::FieldSchema = { .mNumFieldDescriptorElements = sizeof(FutureNullableEventFieldDescriptors)/sizeof(FutureNullableEventFieldDescriptors[0]), .mFields = FutureNullableEventFieldDescriptors, .mSize = sizeof(FutureNullableEvent) }; |
| const nl::Weave::Profiles::DataManagement::EventSchema FutureNullableEvent::Schema = { .mProfileId = kProfileId, .mStructureType = 0x1, .mImportance = nl::Weave::Profiles::DataManagement::ProductionCritical, .mDataSchemaVersion = 2, .mMinCompatibleDataSchemaVersion = 1 }; |
| inline void FutureNullableEvent::SetBaseEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 0); } |
| inline void FutureNullableEvent::SetBaseEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 0); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool FutureNullableEvent::IsBaseEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 0)); } |
| #endif |
| inline void FutureNullableEvent::SetFutureEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 1); } |
| inline void FutureNullableEvent::SetFutureEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 1); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool FutureNullableEvent::IsFutureEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 1)); } |
| #endif |
| inline void FutureNullableEvent::SetExtendedEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 2); } |
| inline void FutureNullableEvent::SetExtendedEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 2); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool FutureNullableEvent::IsExtendedEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 2)); } |
| #endif |
| inline void FutureNullableEvent::SetFutureExtendedEnumNull(void) { SET_FIELD_NULLIFIED_BIT(__nullified_fields__, 3); } |
| inline void FutureNullableEvent::SetFutureExtendedEnumPresent(void) { CLEAR_FIELD_NULLIFIED_BIT(__nullified_fields__, 3); } |
| #if WEAVE_CONFIG_SERIALIZATION_ENABLE_DESERIALIZATION |
| inline bool FutureNullableEvent::IsFutureExtendedEnumPresent(void) { return (!GET_FIELD_NULLIFIED_BIT(__nullified_fields__, 3)); } |
| #endif |
| |
| static void CheckDeserializingNewerVersionNullable(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| uint8_t backingStore[1024]; |
| InitializeEventLogging(context); |
| |
| FutureNullableEvent externalEv = { 0 }; |
| externalEv.baseEnum = 50; |
| externalEv.SetBaseEnumPresent(); |
| externalEv.SetFutureEnumNull(); |
| externalEv.extendedEnum = 70; |
| externalEv.SetExtendedEnumPresent(); |
| externalEv.SetFutureExtendedEnumNull(); |
| |
| event_id_t eventId = nl::LogEvent(&externalEv); |
| |
| TLVReader testReader; |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore), nl::Weave::Profiles::DataManagement::ProductionCritical); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| CurrentNullableEvent deserializedEv = { 0 }; |
| nl::StructureSchemaPointerPair structureSchemaPair; |
| structureSchemaPair.mStructureData = &deserializedEv; |
| structureSchemaPair.mFieldSchema = &CurrentNullableEvent::FieldSchema; |
| |
| err = nl::TLVReaderToDeserializedDataHelper(testReader, nl::Weave::Profiles::DataManagement::kTag_EventData, |
| (void *)&structureSchemaPair, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsBaseEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsBaseEnumPresent() == externalEv.IsBaseEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.baseEnum == externalEv.baseEnum); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsExtendedEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsExtendedEnumPresent() == externalEv.IsExtendedEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.extendedEnum == externalEv.extendedEnum); |
| } |
| |
| static void CheckDeserializingOlderVersionNullable(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| WEAVE_ERROR err; |
| nl::MemoryManagement memMgmt = { malloc, free, realloc }; |
| nl::SerializationContext serializationContext; |
| serializationContext.memMgmt = memMgmt; |
| uint8_t backingStore[1024]; |
| InitializeEventLogging(context); |
| |
| CurrentNullableEvent externalEv = { 0 }; |
| externalEv.baseEnum = 50; |
| externalEv.SetBaseEnumPresent(); |
| externalEv.SetExtendedEnumNull(); |
| |
| event_id_t eventId = nl::LogEvent(&externalEv); |
| |
| TLVReader testReader; |
| err = FetchEventsHelper(testReader, eventId, backingStore, sizeof(backingStore), nl::Weave::Profiles::DataManagement::ProductionCritical); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| |
| FutureNullableEvent deserializedEv = { 0 }; |
| nl::StructureSchemaPointerPair structureSchemaPair; |
| structureSchemaPair.mStructureData = &deserializedEv; |
| structureSchemaPair.mFieldSchema = &FutureNullableEvent::FieldSchema; |
| |
| err = nl::TLVReaderToDeserializedDataHelper(testReader, nl::Weave::Profiles::DataManagement::kTag_EventData, |
| (void *)&structureSchemaPair, &serializationContext); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsBaseEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsBaseEnumPresent() == externalEv.IsBaseEnumPresent()); |
| NL_TEST_ASSERT(inSuite, deserializedEv.baseEnum == externalEv.baseEnum); |
| |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsFutureEnumPresent() == false); |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsExtendedEnumPresent() == false); |
| NL_TEST_ASSERT(inSuite, deserializedEv.IsFutureExtendedEnumPresent() == false); |
| } |
| |
| static void CheckSubscriptionHandlerHelper(nlTestSuite *inSuite, TestLoggingContext *context, bool inLogInfoEvents) |
| { |
| WEAVE_ERROR err; |
| timestamp_t now; |
| size_t counter = 0; |
| ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler subHandler; |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logger = |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| nl::Weave::Profiles::DataManagement::ImportanceType importance; |
| TLVWriter writer; |
| uint8_t backingStore[1024]; |
| |
| event_id_t eid_init_prod, eid_prev_prod, eid_init_info, eid_prev_info, eid; |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| eid_init_prod = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter++); |
| if (inLogInfoEvents) |
| { |
| eid_init_info = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Info, |
| now+5, |
| "Freeform entry %d", counter++); |
| } |
| |
| eid_prev_prod = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now+10, |
| "Freeform entry %d", counter++); |
| |
| if (inLogInfoEvents) |
| { |
| eid_prev_info = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Info, |
| now+15, |
| "Freeform entry %d", counter++); |
| } |
| |
| NL_TEST_ASSERT(inSuite, (eid_init_prod + 1) == eid_prev_prod); |
| if (inLogInfoEvents) |
| { |
| if (nl::Weave::Profiles::DataManagement::LoggingConfiguration::GetInstance().mGlobalImportance >= nl::Weave::Profiles::DataManagement::Info) |
| { |
| NL_TEST_ASSERT(inSuite, (eid_init_info + 1) == eid_prev_info); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, eid_prev_info == 0 && eid_init_info == 0); |
| } |
| } |
| |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger) == false); |
| subHandler.SetEventLogEndpoint(logger); |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Production); |
| writer.Init(backingStore, 1024); |
| CheckLogReadOut(inSuite, context, logger, importance, eid_init_prod, 2); |
| |
| err = logger.FetchEventsSince(writer, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| |
| // If we expect to have logged the Info events above, check the Info logs |
| if (inLogInfoEvents && (nl::Weave::Profiles::DataManagement::LoggingConfiguration::GetInstance().mGlobalImportance >= nl::Weave::Profiles::DataManagement::Info)) |
| { |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Info); |
| writer.Init(backingStore, 1024); |
| CheckLogReadOut(inSuite, context, logger, importance, eid_init_info, 2); |
| err = logger.FetchEventsSince(writer, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| } |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| |
| while (importance != nl::Weave::Profiles::DataManagement::kImportanceType_Invalid) |
| { |
| err = logger.FetchEventsSince(writer, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| importance = subHandler.FindNextImportanceForTransfer(); |
| } |
| |
| // Verify that events are retrieved. |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger)); |
| |
| // Check that a single event will trigger the up to date check |
| |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now + 10, |
| "Freeform entry %d", counter++); |
| |
| NL_TEST_ASSERT(inSuite, (eid_prev_prod + 1) == eid); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger) == false); |
| subHandler.SetEventLogEndpoint(logger); |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Production); |
| |
| // Verify that the read operation will retrieve a single event |
| eid_init_prod = subHandler.GetVendedEvent(importance); |
| CheckLogReadOut(inSuite, context, logger, importance, eid_init_prod, 1); |
| |
| writer.Init(backingStore, 1024); |
| while (importance != nl::Weave::Profiles::DataManagement::kImportanceType_Invalid) |
| { |
| err = logger.FetchEventsSince(writer, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| importance = subHandler.FindNextImportanceForTransfer(); |
| } |
| |
| //Verify that the all events are retrieved |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger)); |
| } |
| |
| static void CheckSubscriptionHandler(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = false; |
| |
| InitializeEventLogging(context); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtZeroProd(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = false; |
| |
| InitializeEventLoggingWithPersistedCounters(context, 0, nl::Weave::Profiles::DataManagement::Production); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtZeroTwoDifferentImportancesProd(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = true; |
| |
| InitializeEventLoggingWithPersistedCounters(context, 0, nl::Weave::Profiles::DataManagement::Production); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtNonZeroProd(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = false; |
| |
| InitializeEventLoggingWithPersistedCounters(context, sEventIdCounterEpoch, nl::Weave::Profiles::DataManagement::Production); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtNonZeroTwoDifferentImportancesProd(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = true; |
| |
| InitializeEventLoggingWithPersistedCounters(context, sEventIdCounterEpoch, nl::Weave::Profiles::DataManagement::Production); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtZeroInfo(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = false; |
| |
| InitializeEventLoggingWithPersistedCounters(context, 0, nl::Weave::Profiles::DataManagement::Info); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtZeroTwoDifferentImportancesInfo(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = true; |
| |
| InitializeEventLoggingWithPersistedCounters(context, 0, nl::Weave::Profiles::DataManagement::Info); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtNonZeroInfo(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = false; |
| |
| InitializeEventLoggingWithPersistedCounters(context, sEventIdCounterEpoch, nl::Weave::Profiles::DataManagement::Info); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckSubscriptionHandlerCountersStartAtNonZeroTwoDifferentImportancesInfo(nlTestSuite *inSuite, void *inContext) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| const bool aLogInfoEvents = true; |
| |
| InitializeEventLoggingWithPersistedCounters(context, sEventIdCounterEpoch, nl::Weave::Profiles::DataManagement::Info); |
| |
| CheckSubscriptionHandlerHelper(inSuite, context, aLogInfoEvents); |
| } |
| |
| static void CheckExternalEvents(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| TLVReader testReader; |
| event_id_t eid_in, eid = 0; |
| int i; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| |
| for (i = 0; i < 10; i++) |
| { |
| eid_in = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", i); |
| } |
| |
| // register callback |
| err = LogMockExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| for (i = 0; i < 10; i++) |
| { |
| eid_in = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", i+10); |
| } |
| |
| // positive case where events lie within event range in importance buffer |
| // retrieve all events in order |
| for (int j = 0; j < 3; j++) |
| { |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid); |
| NL_TEST_ASSERT(inSuite, eid == 10*(static_cast<event_id_t>(j) + 1)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| } |
| |
| // retrieve events starting in the middle of external events |
| eid = 14; |
| for (int x = 0; x < 2; x++) |
| { |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid); |
| NL_TEST_ASSERT(inSuite, eid == 10*(static_cast<event_id_t>(x) + 2)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| } |
| |
| // log many events so no longer trying to fetch external events |
| for (i = 0; i < 100; i++) |
| { |
| eid_in = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", i); |
| } |
| |
| { |
| utc_timestamp_t utc_tmp; |
| timestamp_t time_tmp; |
| event_id_t eid_tmp; |
| |
| eid = 0; |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV); |
| NL_TEST_ASSERT(inSuite, eid == eid_in + 1); |
| |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| ReadFirstEventHeader(testReader, time_tmp, utc_tmp, eid_tmp); |
| NL_TEST_ASSERT(inSuite, eid_tmp >= 20); |
| } |
| } |
| |
| static void CheckExternalEventsMultipleCallbacks(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| TLVReader testReader; |
| event_id_t eid = 0; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| |
| err = LogMockExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| for (int i = 0; i < 10; i++) |
| { |
| (void)nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry %d", i); |
| } |
| |
| err = LogMockExternalEvents(10, 2); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = LogMockExternalEvents(10, 3); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_NO_MEMORY); |
| |
| ClearMockExternalEvents(1); |
| |
| // even after clearing the first callback, we should receive 3 separate error codes. |
| for (int j = 0; j < 3; j++) |
| { |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| err = nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance().FetchEventsSince(testWriter, nl::Weave::Profiles::DataManagement::Production, eid); |
| NL_TEST_ASSERT(inSuite, eid == 10*(static_cast<event_id_t>(j) + 1)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| |
| if (context->mVerbose) |
| { |
| testReader.Init(gLargeMemoryBackingStore, testWriter.GetLengthWritten()); |
| nl::Weave::TLV::Debug::Dump(testReader, SimpleDumpWriter); |
| } |
| } |
| } |
| |
| static void RegressionWatchdogBug(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| //TLVReader testReader; |
| event_id_t eid = 0; |
| ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler subHandler; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logger = |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| nl::Weave::Profiles::DataManagement::ImportanceType importance; |
| |
| InitializeEventLogging(context); |
| |
| err = LogMockExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = LogMockExternalEvents(10, 2); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| ClearMockExternalEvents(1); |
| ClearMockExternalEvents(2); |
| eid = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "Freeform entry"); |
| |
| NL_TEST_ASSERT(inSuite, eid == 20); |
| |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| |
| subHandler.SetEventLogEndpoint(logger); |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Production); |
| while (importance != nl::Weave::Profiles::DataManagement::kImportanceType_Invalid) |
| { |
| err = logger.FetchEventsSince(testWriter, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| importance = subHandler.FindNextImportanceForTransfer(); |
| } |
| // Verify that events are retrieved. |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger)); |
| |
| } |
| |
| static void RegressionWatchdogBug_EventRemoval(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| //TLVReader testReader; |
| event_id_t eid = 0; |
| timestamp_t now; |
| ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler subHandler; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logger = |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| nl::Weave::Profiles::DataManagement::ImportanceType importance; |
| |
| InitializeEventLogging(context); |
| |
| err = LogMockDebugExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = LogMockDebugExternalEvents(10, 2); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| eid = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Debug, |
| "Freeform entry"); |
| NL_TEST_ASSERT(inSuite, eid == 20); |
| |
| eid = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Debug, |
| "Freeform entry"); |
| NL_TEST_ASSERT(inSuite, eid == 21); |
| |
| eid = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Debug, |
| "Freeform entry"); |
| NL_TEST_ASSERT(inSuite, eid == 22); |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| for (size_t counter=0; counter < 100; counter++) |
| { |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| NL_TEST_ASSERT(inSuite, eid == counter); |
| |
| now+=10; |
| } |
| |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| |
| subHandler.SetEventLogEndpoint(logger); |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Production); |
| while (importance != nl::Weave::Profiles::DataManagement::kImportanceType_Invalid) |
| { |
| err = logger.FetchEventsSince(testWriter, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| importance = subHandler.FindNextImportanceForTransfer(); |
| } |
| // Verify that events are retrieved. |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger)); |
| |
| } |
| |
| static void RegressionWatchdogBug_ExternalEventState(nlTestSuite *inSuite, void *inContext) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| //TLVReader testReader; |
| event_id_t eid = 0; |
| timestamp_t now; |
| ::nl::Weave::Profiles::DataManagement::TestSubscriptionHandler subHandler; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| nl::Weave::Profiles::DataManagement::LoggingManagement &logger = |
| nl::Weave::Profiles::DataManagement::LoggingManagement::GetInstance(); |
| nl::Weave::Profiles::DataManagement::ImportanceType importance; |
| |
| InitializeEventLogging(context); |
| |
| err = LogMockExternalEvents(10, 1); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| err = LogMockExternalEvents(10, 2); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| eid = nl::Weave::Profiles::DataManagement::LogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| "F"); |
| |
| NL_TEST_ASSERT(inSuite, eid == 20); |
| |
| ClearMockExternalEvents(1); |
| |
| ClearMockExternalEvents(2); |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| for (size_t counter=0; counter < 100; counter++) |
| { |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| NL_TEST_ASSERT(inSuite, eid == (counter + 21)); |
| now+=10; |
| } |
| |
| testWriter.Init(gLargeMemoryBackingStore, sizeof(gLargeMemoryBackingStore)); |
| |
| subHandler.SetEventLogEndpoint(logger); |
| |
| importance = subHandler.FindNextImportanceForTransfer(); |
| NL_TEST_ASSERT(inSuite, importance == nl::Weave::Profiles::DataManagement::Production); |
| while (importance != nl::Weave::Profiles::DataManagement::kImportanceType_Invalid) |
| { |
| err = logger.FetchEventsSince(testWriter, importance, subHandler.GetVendedEvent(importance)); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_END_OF_TLV || err == WEAVE_NO_ERROR); |
| importance = subHandler.FindNextImportanceForTransfer(); |
| } |
| // Verify that events are retrieved. |
| NL_TEST_ASSERT(inSuite, subHandler.VerifyTraversingImportance()); |
| NL_TEST_ASSERT(inSuite, subHandler.CheckEventUpToDate(logger)); |
| |
| } |
| |
| static void CheckExternalEventsMultipleFetches(nlTestSuite *inSuite, void *inContext) |
| { |
| uint8_t smallMemoryBackingStore[256]; |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TLVWriter testWriter; |
| TLVReader testReader; |
| event_id_t fetchId = 0; |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| |
| err = LogMockExternalEvents(10, 0); |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| |
| while ((fetchId < 10) && (err == WEAVE_NO_ERROR)) |
| { |
| timestamp_t time_tmp; |
| utc_timestamp_t utc_tmp = 0; |
| event_id_t eid_tmp = 0; |
| |
| testWriter.Init(smallMemoryBackingStore, sizeof(smallMemoryBackingStore)); |
| err = LoggingManagement::GetInstance().FetchEventsSince(testWriter, Production, fetchId); |
| if (fetchId < 10) |
| { |
| NL_TEST_ASSERT(inSuite, err == WEAVE_ERROR_BUFFER_TOO_SMALL); |
| } |
| else |
| { |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| } |
| |
| if (err == WEAVE_ERROR_BUFFER_TOO_SMALL) |
| { |
| err = WEAVE_NO_ERROR; |
| } |
| |
| testReader.Init(smallMemoryBackingStore, testWriter.GetLengthWritten()); |
| ReadFirstEventHeader(testReader, time_tmp, utc_tmp, eid_tmp); |
| // eid_tmp is unsigned and so always positive |
| NL_TEST_ASSERT(inSuite, eid_tmp < fetchId); |
| NL_TEST_ASSERT(inSuite, utc_tmp != 0); |
| } |
| |
| NL_TEST_ASSERT(inSuite, err == WEAVE_NO_ERROR); |
| } |
| |
| static void CheckShutdownLogic(nlTestSuite *inSuite, void *inContext) |
| { |
| event_id_t eid = 0; |
| int counter = 1; |
| timestamp_t now; |
| |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(inContext); |
| |
| InitializeEventLogging(context); |
| DestroyEventLogging(context); |
| |
| now = static_cast<timestamp_t>(System::Timer::GetCurrentEpoch()); |
| |
| eid = FastLogFreeform( |
| nl::Weave::Profiles::DataManagement::Production, |
| now, |
| "Freeform entry %d", counter); |
| |
| NL_TEST_ASSERT(inSuite, eid == 0); |
| } |
| //Test Suite |
| |
| /** |
| * Test Suite that lists all the test functions. |
| */ |
| static const nlTest sTests[] = { |
| NL_TEST_DEF("Simple Event Log Test", CheckLogEventBasics), |
| NL_TEST_DEF("Simple Freeform Log Test", CheckLogFreeform), |
| NL_TEST_DEF("Simple Pre-formatted Log Test", CheckLogPreformed), |
| NL_TEST_DEF("Schema Generated Log Test", CheckSchemaGeneratedLogging), |
| NL_TEST_DEF("Check Byte String Field Type", CheckByteStringFieldType), |
| NL_TEST_DEF("Check Byte String Array", CheckByteStringArray), |
| NL_TEST_DEF("Check Log eviction", CheckEvict), |
| NL_TEST_DEF("Check Fetch Events", CheckFetchEvents), |
| NL_TEST_DEF("Check Large Events", CheckLargeEvents), |
| NL_TEST_DEF("Check Fetch Event Timestamps", CheckFetchTimestamps), |
| NL_TEST_DEF("Basic Deserialization Test", CheckBasicEventDeserialization), |
| NL_TEST_DEF("Complex Deserialization Test", CheckComplexEventDeserialization), |
| NL_TEST_DEF("Empty Array Deserialization Test", CheckEmptyArrayEventDeserialization), |
| NL_TEST_DEF("Simple Nullable Fields Test", CheckNullableFieldsSimple), |
| NL_TEST_DEF("Complex Nullable Fields Test", CheckNullableFieldsComplex), |
| NL_TEST_DEF("Check Deserializing an Event from a Newer Version", CheckDeserializingNewerVersion), |
| NL_TEST_DEF("Check Deserializing an Event from an Older Version", CheckDeserializingOlderVersion), |
| NL_TEST_DEF("Check Deserializing an Event from a Newer Version with Nullables", CheckDeserializingNewerVersionNullable), |
| NL_TEST_DEF("Check Deserializing an Event from an Older Version with Nullables", CheckDeserializingOlderVersionNullable), |
| NL_TEST_DEF("Subscription Handler accounting", CheckSubscriptionHandler), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at zero, same importances, Production global importance", CheckSubscriptionHandlerCountersStartAtZeroProd), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at zero, two different importances, Production global importance", CheckSubscriptionHandlerCountersStartAtZeroTwoDifferentImportancesProd), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at non-zero, same importances, Production global importance", CheckSubscriptionHandlerCountersStartAtNonZeroProd), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at non-zero, two different importances, Production global importance", CheckSubscriptionHandlerCountersStartAtNonZeroTwoDifferentImportancesProd), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at zero, same importances, Info global importance", CheckSubscriptionHandlerCountersStartAtZeroInfo), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at zero, two different importances, Info global importance", CheckSubscriptionHandlerCountersStartAtZeroTwoDifferentImportancesInfo), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at non-zero, same importances, Info global importance", CheckSubscriptionHandlerCountersStartAtNonZeroInfo), |
| NL_TEST_DEF("Subscription Handler accounting, PersistedCounters start at non-zero, two different importances, Info global importance", CheckSubscriptionHandlerCountersStartAtNonZeroTwoDifferentImportancesInfo), |
| NL_TEST_DEF("Check External Events Basic", CheckExternalEvents), |
| NL_TEST_DEF("Check External Events Multiple Callbacks", CheckExternalEventsMultipleCallbacks), |
| NL_TEST_DEF("Check External Events Multiple Fetches", CheckExternalEventsMultipleFetches), |
| NL_TEST_DEF("Check Drop Events", CheckDropEvents), |
| NL_TEST_DEF("Check Shutdown Logic", CheckShutdownLogic), |
| NL_TEST_DEF("Check WDM offload trigger", CheckWDMOffloadTrigger), |
| NL_TEST_DEF("Regression: watchdog bug", RegressionWatchdogBug), |
| NL_TEST_DEF("Regression: external event cleanup", RegressionWatchdogBug_EventRemoval), |
| NL_TEST_DEF("Regression: external event, external clear call", RegressionWatchdogBug_ExternalEventState), |
| NL_TEST_DEF("Check version 1 data schema compatibility encoding + decoding", CheckVersion1DataCompatibility), |
| NL_TEST_DEF("Check forward data compatibility encoding + decoding", CheckForwardDataCompatibility), |
| NL_TEST_DEF("Check data incompatible encoding + decoding", CheckDataIncompatibility), |
| NL_TEST_SENTINEL() |
| }; |
| |
| int main(int argc, char *argv[]) |
| { |
| nl::Weave::MockPlatform::gTestPlatformTimeFns.GetSystemTimeMs = Private::GetSystemTimeMs; |
| nl::Weave::MockPlatform::gTestPlatformTimeFns.SetSystemTime = Private::SetSystemTime; |
| |
| if (!ParseArgsFromEnvVar(TOOL_NAME, TOOL_OPTIONS_ENV_VAR_NAME, gToolOptionSets, NULL, true) || |
| !ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets)) |
| { |
| exit(EXIT_FAILURE); |
| } |
| |
| nlTestSuite theSuite = { |
| "weave-event-log", |
| &sTests[0], |
| TestSetup, |
| TestTeardown |
| }; |
| |
| gTestLoggingContext.mReinitializeBDXUpload = true; |
| |
| // Generate machine-readable, comma-separated value (CSV) output. |
| nl_test_set_output_style(OUTPUT_CSV); |
| |
| // Run test suit against one context |
| nlTestRunner(&theSuite, &gTestLoggingContext); |
| |
| return nlTestRunnerStats(&theSuite); |
| } |
| |
| bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg) |
| { |
| switch (id) |
| { |
| case 't': |
| gBDXContext.mUseTCP = true; |
| break; |
| case 'u': |
| gBDXContext.mUseTCP = false; |
| break; |
| case 'D': |
| gBDXContext.DestIPAddrStr = arg; |
| gTestLoggingContext.bdx = true; |
| break; |
| case 'p': |
| if (!ParseInt(arg, gBDXContext.DestNodeId)) |
| { |
| PrintArgError("%s: Invalid value specified for destination node id: %s\n", progName, arg); |
| return false; |
| } |
| gTestLoggingContext.bdx = true; |
| break; |
| case 'd': |
| gTestLoggingContext.mVerbose = true; |
| break; |
| case 's': |
| if (!ParseInt(arg, gBDXContext.mStartingBlock)) |
| { |
| PrintArgError("%s: Invalid value specified for start block: %s\n", progName, arg); |
| return false; |
| } |
| break; |
| default: |
| PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| static void PrepareBinding(TestLoggingContext *context) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| Binding *binding = NULL; |
| |
| if (!context->mBinding) { |
| binding = context->mExchangeMgr->NewBinding(HandleBindingEvent, context); |
| if (binding == NULL) |
| { |
| printf("NewBinding failed\n"); |
| return; |
| } |
| |
| Binding::Configuration bindingConfig = binding->BeginConfiguration() |
| .Target_NodeId(gBDXContext.DestNodeId) |
| .Transport_UDP() |
| .Security_None(); |
| |
| if (gBDXContext.DestIPAddrStr != NULL && nl::Inet::IPAddress::FromString(gBDXContext.DestIPAddrStr, gBDXContext.DestIPAddr)) |
| { |
| bindingConfig.TargetAddress_IP(gBDXContext.DestIPAddr); |
| |
| err = bindingConfig.PrepareBinding(); |
| if (err != WEAVE_NO_ERROR) |
| { |
| printf("PrepareBinding failed\n"); |
| return; |
| } |
| } |
| |
| context->mBinding = binding; |
| } |
| } |
| |
| static WEAVE_ERROR InitSubscriptionClient(TestLoggingContext *context) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| if (!context->mSubClient) { |
| err = SubscriptionEngine::GetInstance()->NewClient(&context->mSubClient, context->mBinding, NULL, NULL, NULL, 0); |
| } |
| |
| return err; |
| } |
| |
| static void HandleBindingEvent(void *const appState, const Binding::EventType event, const Binding::InEventParam &inParam, Binding::OutEventParam &outParam) |
| { |
| TestLoggingContext *context = static_cast<TestLoggingContext *>(appState); |
| |
| switch (event) |
| { |
| case Binding::kEvent_BindingReady: |
| gLogBDXUpload.StartUpload(context->mBinding); |
| break; |
| case Binding::kEvent_PrepareFailed: |
| printf("Binding Prepare failed\n"); |
| break; |
| default: |
| Binding::DefaultEventHandler(appState, event, inParam, outParam); |
| break; |
| } |
| } |
| |
| static void StartClientConnection(System::Layer *systemLayer, void *appState, System::Error error) |
| { |
| BDXContext *ctx = static_cast<BDXContext *>(appState); |
| |
| printf("@@@ 0 StartClientConnection entering (Con: %p)\n", Con); |
| |
| if (Con != NULL && Con->State == WeaveConnection::kState_Closed) |
| { |
| printf("@@@ 1 remove previous con (currently closed)\n"); |
| Con->Close(); |
| Con = NULL; |
| } |
| |
| // Do nothing if a connect attempt is already in progress. |
| if (Con != NULL) |
| { |
| printf("@@@ 2 (Con: %p) previous Con likely hanging\n", Con); |
| return; |
| } |
| |
| //TODO: move this to BDX logic |
| Con = MessageLayer.NewConnection(); |
| if (Con == NULL) |
| { |
| printf("@@@ 3 WeaveConnection.Connect failed: no memory\n"); |
| return; |
| } |
| printf("@@@ 3+ (Con: %p)\n", Con); |
| Con->OnConnectionComplete = HandleConnectionComplete; |
| Con->OnConnectionClosed = HandleConnectionClosed; |
| |
| printf("@@@ 3++ (DestNodeId: %" PRIX64 ", DestIPAddrStr: %s)\n", ctx->DestNodeId, ctx->DestIPAddrStr); |
| |
| WEAVE_ERROR err; |
| if (ctx->DestIPAddrStr) |
| { |
| IPAddress::FromString(ctx->DestIPAddrStr, ctx->DestIPAddr); |
| err = Con->Connect(ctx->DestNodeId, kWeaveAuthMode_Unauthenticated, ctx->DestIPAddr); |
| } |
| else // not specified, derive from NodeID |
| { |
| err = Con->Connect(ctx->DestNodeId); |
| } |
| |
| if (err != WEAVE_NO_ERROR) |
| { |
| printf("@@@ 4 WeaveConnection.Connect failed: %X (%s)\n", err, ErrorStr(err)); |
| Con->Close(); |
| Con = NULL; |
| return; |
| } |
| |
| ConnectTry++; |
| printf("@@@ 5 StartClientConnection exiting\n"); |
| } |
| |
| void HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR conErr) |
| { |
| printf("@@@ 1 HandleConnectionComplete entering\n"); |
| |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| char ipAddrStr[64]; |
| |
| con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr)); |
| |
| if (conErr != WEAVE_NO_ERROR) |
| { |
| printf("Connection FAILED to node %" PRIX64 " (%s): %s\n", con->PeerNodeId, ipAddrStr, ErrorStr(conErr)); |
| con->Close(); |
| Con = NULL; |
| |
| if (ConnectTry < ConnectMaxTry) |
| { |
| err = SystemLayer.StartTimer(ConnectInterval, StartClientConnection, &gBDXContext); |
| if (err != WEAVE_NO_ERROR) |
| { |
| printf("Inet.StartTimer failed\n"); |
| exit(-1); |
| } |
| } |
| else |
| { |
| printf("Connection FAILED to node %" PRIX64 " (%s) after %d attempts\n", con->PeerNodeId, ipAddrStr, ConnectTry); |
| exit(-1); |
| } |
| |
| ClientConEstablished = false; |
| return; |
| } |
| |
| printf("Connection established to node %" PRIX64 " (%s)\n", con->PeerNodeId, ipAddrStr); |
| |
| ClientConEstablished = true; |
| |
| //Send the ReceiveInit or SendInit request |
| if (Con != NULL) |
| { |
| // Kick LogBDXUpload |
| } |
| else |
| { |
| printf("Non-connection Init Requests not supported!\n"); |
| exit(-1); |
| } |
| |
| if (err == WEAVE_NO_ERROR) |
| { |
| WaitingForBDXResp = true; |
| } |
| |
| printf("@@@ 7 HandleConnectionComplete exiting\n"); |
| } |
| |
| void HandleConnectionClosed(WeaveConnection *con, WEAVE_ERROR conErr) |
| { |
| char ipAddrStr[64]; |
| con->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr)); |
| |
| if (conErr == WEAVE_NO_ERROR) |
| printf("Connection closed to node %" PRIX64 " (%s)\n", con->PeerNodeId, ipAddrStr); |
| else |
| printf("Connection ABORTED to node %" PRIX64 " (%s): %s\n", con->PeerNodeId, ipAddrStr, ErrorStr(conErr)); |
| |
| WaitingForBDXResp = false; |
| |
| if (Listening) |
| con->Close(); |
| else if (con == Con) |
| { |
| con->Close(); |
| Con = NULL; |
| } |
| } |