blob: cffab7b9b0bd8fdf0dd8ddf18514f4f1179a15c2 [file] [log] [blame]
/*
*
* Copyright (c) 2016-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file implements test app for the Weave Data Management(WDM) Next Profile.
*
*
*/
#define __STDC_FORMAT_MACROS
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.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 "ToolCommon.h"
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/WeaveVersion.h>
#include "MockLoggingManager.h"
#include "MockWdmSubscriptionInitiator.h"
#include <Weave/Support/CodeUtils.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/common/CommonProfile.h>
#include <Weave/Profiles/time/WeaveTime.h>
#include <SystemLayer/SystemTimer.h>
#include <time.h>
#include "MockLoggingManager.h"
#include "MockWdmSubscriptionInitiator.h"
#include "MockWdmSubscriptionResponder.h"
#include "MockWdmViewClient.h"
#include "MockWdmViewServer.h"
#include "WdmNextPerfUtility.h"
#include "TestWdmSubscriptionlessNotification.h"
#include "MockWdmNodeOptions.h"
using nl::Inet::IPAddress;
using namespace nl::Weave;
using namespace nl::Weave::TLV;
using namespace nl::Weave::Profiles;
using nl::Weave::WeaveExchangeManager;
#define TOOL_NAME "TestWdmNext"
static void HandleWdmCompleteTest();
static void HandleError();
// events
EventGenerator * gEventGenerator = NULL;
uint32_t TestWdmSublessNotifyDelayMsec = 6000;
static HelpOptions gHelpOptions(
TOOL_NAME,
"Usage: " TOOL_NAME " [<options>]\n",
WEAVE_VERSION_STRING "\n" WEAVE_TOOL_COPYRIGHT
);
static OptionSet *gToolOptionSets[] =
{
&gTestWdmNextOptions,
&gMockWdmNodeOptions,
&gNetworkOptions,
&gWeaveNodeOptions,
&gWeaveSecurityMode,
&gFaultInjectionOptions,
&gHelpOptions,
&gCASEOptions,
&gGroupKeyEncOptions,
NULL
};
static int32_t GetNumFaultInjectionEventsAvailable(void)
{
int32_t retval = 0;
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
MockWdmSubscriptionInitiator *initiator = MockWdmSubscriptionInitiator::GetInstance();
retval = initiator->GetNumFaultInjectionEventsAvailable();
#endif
return retval;
}
static void ExpireTimer(int32_t argument)
{
ExchangeMgr.ExpireExchangeTimers();
}
int main(int argc, char *argv[])
{
WEAVE_ERROR err;
WdmNextPerfUtility &TimeRef = *WdmNextPerfUtility::Instance();
struct timeval sleepTime;
time_t begin, end;
double seconds = 0;
sleepTime.tv_sec = 0;
sleepTime.tv_usec = 100000;
nl::Weave::System::Stats::Snapshot before;
nl::Weave::System::Stats::Snapshot after;
const bool printStats = true;
gMockWdmNodeOptions.mWdmUpdateMaxNumberOfTraits = MockWdmSubscriptionInitiator::GetNumUpdatableTraits();
InitToolCommon();
SetupFaultInjectionContext(argc, argv,
GetNumFaultInjectionEventsAvailable, ExpireTimer);
SetSignalHandler(DoneOnHandleSIGUSR1);
if (argc == 1)
{
gHelpOptions.PrintBriefUsage(stderr);
exit(EXIT_FAILURE);
}
if (!ParseArgsFromEnvVar(TOOL_NAME, TOOL_OPTIONS_ENV_VAR_NAME, gToolOptionSets, NULL, true) ||
!ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets) ||
!ResolveWeaveNetworkOptions(TOOL_NAME, gWeaveNodeOptions, gNetworkOptions))
{
exit(EXIT_FAILURE);
}
// This test program enables faults and stats prints always (no option taken from the CLI)
gFaultInjectionOptions.DebugResourceUsage = true;
gFaultInjectionOptions.PrintFaultCounters = true;
InitSystemLayer();
InitNetwork();
InitWeaveStack(true, true);
InitializeEventLogging(&ExchangeMgr);
switch (gMockWdmNodeOptions.mWdmRoleInTest)
{
case 0:
break;
#if ENABLE_VIEW_TEST
case kToolOpt_WdmSimpleViewClient:
if (gMockWdmNodeOptions.mWdmPublisherNodeId != kAnyNodeId)
{
err = MockWdmViewClient::GetInstance()->Init(&ExchangeMgr, gMockWdmNodeOptions.mTestCaseId);
FAIL_ERROR(err, "MockWdmViewClient.Init failed");
MockWdmViewClient::GetInstance()-> onCompleteTest = HandleWdmCompleteTest;
}
else
{
err = WEAVE_ERROR_INVALID_ARGUMENT;
FAIL_ERROR(err, "Simple View Client requires node ID to some publisher");
}
break;
case kToolOpt_WdmSimpleViewServer:
err = MockWdmViewServer::GetInstance()->Init(&ExchangeMgr, gMockWdmNodeOptions.mTestCaseId);
FAIL_ERROR(err, "MockWdmViewServer.Init failed");
break;
#endif // ENABLE_VIEW_TEST
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmSimpleSublessNotifyClient:
err = TestWdmSubscriptionlessNotificationReceiver::GetInstance()->Init(&ExchangeMgr);
FAIL_ERROR(err, "TestWdmSubscriptionlessNotificationReceiver.Init failed");
TestWdmSubscriptionlessNotificationReceiver::GetInstance()->OnTestComplete = HandleWdmCompleteTest;
TestWdmSubscriptionlessNotificationReceiver::GetInstance()->OnError = HandleError;
break;
case kToolOpt_WdmSimpleSublessNotifyServer:
time(&begin);
while (seconds * 1000 < TestWdmSublessNotifyDelayMsec)
{
ServiceNetwork(sleepTime);
time(&end);
seconds = difftime(end, begin);
}
printf("delay %d milliseconds\n", TestWdmSublessNotifyDelayMsec);
seconds = 0;
if (gMockWdmNodeOptions.mWdmSublessNotifyDestNodeId != kAnyNodeId)
{
err = TestWdmSubscriptionlessNotificationSender::GetInstance()->Init(&ExchangeMgr,
gMockWdmNodeOptions.mWdmUseSubnetId,
gMockWdmNodeOptions.mWdmSublessNotifyDestNodeId);
FAIL_ERROR(err, "TestWdmSubscriptionlessNotificationSender.Init failed");
}
break;
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmInitMutualSubscription:
case kToolOpt_WdmSubscriptionClient:
if (gMockWdmNodeOptions.mWdmPublisherNodeId != kAnyNodeId)
{
err = MockWdmSubscriptionInitiator::GetInstance()->Init(&ExchangeMgr,
gGroupKeyEncOptions.GetEncKeyId(),
gWeaveSecurityMode.SecurityMode,
gMockWdmNodeOptions);
FAIL_ERROR(err, "MockWdmSubscriptionInitiator.Init failed");
MockWdmSubscriptionInitiator::GetInstance()->onCompleteTest = HandleWdmCompleteTest;
MockWdmSubscriptionInitiator::GetInstance()->onError = HandleError;
}
else
{
err = WEAVE_ERROR_INVALID_ARGUMENT;
FAIL_ERROR(err, "MockWdmSubscriptionInitiator requires node ID to some publisher");
}
break;
case kToolOpt_WdmRespMutualSubscription:
case kToolOpt_WdmSubscriptionPublisher:
if (gMockWdmNodeOptions.mEnableRetry)
{
err = WEAVE_ERROR_INVALID_ARGUMENT;
FAIL_ERROR(err, "MockWdmSubcriptionResponder is incompatible with --enable-retry");
}
err = MockWdmSubscriptionResponder::GetInstance()->Init(&ExchangeMgr,
gMockWdmNodeOptions);
FAIL_ERROR(err, "MockWdmSubscriptionResponder.Init failed");
MockWdmSubscriptionResponder::GetInstance()->onCompleteTest = HandleWdmCompleteTest;
MockWdmSubscriptionResponder::GetInstance()->onError = HandleError;
if (gTestWdmNextOptions.mClearDataSinkState)
{
MockWdmSubscriptionResponder::GetInstance()->ClearDataSinkState();
}
break;
default:
err = WEAVE_ERROR_INVALID_ARGUMENT;
FAIL_ERROR(err, "WdmRoleInTest is invalid");
};
nl::Weave::Stats::UpdateSnapshot(before);
for (uint32_t iteration = 1; iteration <= gTestWdmNextOptions.mTestIterations; iteration++)
{
Done = false;
#ifdef ENABLE_WDMPERFDATA
TimeRef();
#endif //ENABLE_WDMPERFDATA
switch (gMockWdmNodeOptions.mWdmRoleInTest)
{
case 0:
break;
#if ENABLE_VIEW_TEST
case kToolOpt_WdmSimpleViewClient:
if (gTestWdmNextOptions.mClearDataSinkState)
{
MockWdmViewClient::GetInstance()->ClearDataSinkState();
}
err = MockWdmViewClient::GetInstance()->StartTesting(WdmPublisherNodeId, WdmUseSubnetId);
FAIL_ERROR(err, "MockWdmViewClient.StartTesting failed");
break;
#endif
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmSimpleSublessNotifyClient:
break;
case kToolOpt_WdmSimpleSublessNotifyServer:
if (gMockWdmNodeOptions.mWdmSublessNotifyDestNodeId != kAnyNodeId)
{
err = TestWdmSubscriptionlessNotificationSender::GetInstance()->SendSubscriptionlessNotify();
Done = true;
FAIL_ERROR(err, "TestWdmSubscriptionlessNotificationSender.SendSubscriptionlessNotify failed");
}
break;
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
case kToolOpt_WdmInitMutualSubscription:
case kToolOpt_WdmSubscriptionClient:
if (gTestWdmNextOptions.mClearDataSinkState)
{
MockWdmSubscriptionInitiator::GetInstance()->ClearDataSinkState();
}
err = MockWdmSubscriptionInitiator::GetInstance()->StartTesting(gMockWdmNodeOptions.mWdmPublisherNodeId, gMockWdmNodeOptions.mWdmUseSubnetId);
if (err != WEAVE_NO_ERROR)
{
printf("\nMockWdmSubscriptionInitiator.StartTesting failed: %s\n", ErrorStr(err));
Done = true;
}
//FAIL_ERROR(err, "MockWdmSubscriptionInitiator.StartTesting failed");
break;
default:
printf("TestWdmNext server is ready\n");
};
PrintNodeConfig();
switch (gMockWdmNodeOptions.mEventGeneratorType)
{
case MockWdmNodeOptions::kGenerator_None:
gEventGenerator = NULL;
break;
case MockWdmNodeOptions::kGenerator_TestDebug:
gEventGenerator = GetTestDebugGenerator();
break;
case MockWdmNodeOptions::kGenerator_TestLiveness:
gEventGenerator = GetTestLivenessGenerator();
break;
case MockWdmNodeOptions::kGenerator_TestSecurity:
gEventGenerator = GetTestSecurityGenerator();
break;
case MockWdmNodeOptions::kGenerator_TestTelemetry:
gEventGenerator = GetTestTelemetryGenerator();
break;
case MockWdmNodeOptions::kGenerator_TestTrait:
gEventGenerator = GetTestTraitGenerator();
break;
case MockWdmNodeOptions::kGenerator_NumItems:
default:
gEventGenerator = NULL;
break;
}
if (gEventGenerator != NULL)
{
printf("Starting Event Generator\n");
MockEventGenerator::GetInstance()->Init(&ExchangeMgr, gEventGenerator, gMockWdmNodeOptions.mTimeBetweenEvents, true);
}
printf("Start service network loop\n");
while (!Done)
{
ServiceNetwork(sleepTime);
}
printf("End service network loop\n");
MockEventGenerator::GetInstance()->SetEventGeneratorStop();
if (gEventGenerator != NULL)
{
while (!MockEventGenerator::GetInstance()->IsEventGeneratorStopped())
{
ServiceNetwork(sleepTime);
}
}
switch (gMockWdmNodeOptions.mWdmRoleInTest)
{
case kToolOpt_WdmInitMutualSubscription:
case kToolOpt_WdmSubscriptionClient:
if (gTestWdmNextOptions.mClearDataSinkState)
{
MockWdmSubscriptionInitiator::GetInstance()->Cleanup();
}
break;
default:
break;
}
#ifdef ENABLE_WDMPERFDATA
TimeRef();
TimeRef.SetPerf();
TimeRef.ReportPerf();
#endif //ENABLE_WDMPERFDATA
if (gSigusr1Received)
{
printf("gSigusr1Received\n");
break;
}
time(&begin);
if (gTestWdmNextOptions.mTestDelayBetweenIterationMsec != 0)
{
while (seconds * 1000 < gTestWdmNextOptions.mTestDelayBetweenIterationMsec)
{
ServiceNetwork(sleepTime);
time(&end);
seconds = difftime(end, begin);
}
printf("delay %d milliseconds\n", gTestWdmNextOptions.mTestDelayBetweenIterationMsec);
seconds = 0;
}
else
{
printf("no delay\n");
}
printf("Current completed test iteration is %d\n", iteration);
}
MockWdmSubscriptionInitiator::GetInstance()->PrintVersionsLog();
MockWdmSubscriptionInitiator::GetInstance()->Cleanup();
MockWdmSubscriptionResponder::GetInstance()->PrintVersionsLog();
if (gTestWdmNextOptions.mSavePerfData)
{
TimeRef.SaveToFile();
}
TimeRef.Remove();
ProcessStats(before, after, printStats, NULL);
PrintFaultInjectionCounters();
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
if (gMockWdmNodeOptions.mWdmRoleInTest == kToolOpt_WdmSimpleSublessNotifyServer)
{
err = TestWdmSubscriptionlessNotificationSender::GetInstance()->Shutdown();
FAIL_ERROR(err, "TestWdmSubscriptionlessNotificationSender.Shutdown failed");
}
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
ShutdownWeaveStack();
ShutdownNetwork();
ShutdownSystemLayer();
return 0;
}
static void HandleWdmCompleteTest()
{
if (gMockWdmNodeOptions.mEnableStopTest)
{
printf("HandleWdmCompleteTest: Done = true\n");
Done = true;
}
}
static void HandleError()
{
printf("HandleError: Done = true\n");
Done = true;
}