blob: ebaa88b3fffbcf3b802fa214b891b1227eafbfb2 [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 the Weave Data Management mock view server.
*
*/
#define WEAVE_CONFIG_ENABLE_LOG_FILE_LINE_FUNC_ON_ERROR 1
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif // __STDC_FORMAT_MACROS
#if 0 // TODO: Need to fix this but not a high priority. See WEAV-1348
#include <Weave/Core/WeaveError.h>
#include <Weave/Core/WeaveSecurityMgr.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Core/WeaveTLVDebug.hpp>
#include "MockWdmViewServer.h"
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/data-management/DataManagement.h>
#include "MockTraitSchemas.h"
using nl::Weave::System::PacketBuffer;
#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
using namespace nl::Weave::Profiles::DataManagement;
/**
* Log the specified message in the form of @a aFormat.
*
* @param[in] aFormat A pointer to a NULL-terminated C string with
* C Standard Library-style format specifiers
* containing the log message to be formatted and
* logged.
* @param[in] ... An argument list whose elements should correspond
* to the format specifiers in @a aFormat.
*
*/
void TLVPrettyPrinter(const char *aFormat, ...)
{
va_list args;
va_start(args, aFormat);
// There is no proper Weave logging routine for us to use here
vprintf(aFormat, args);
va_end(args);
}
WEAVE_ERROR DebugPrettyPrint(nl::Weave::TLV::TLVReader & aReader)
{
return nl::Weave::TLV::Debug::Dump(aReader, TLVPrettyPrinter);
}
class MockWdmViewServerImpl: public MockWdmViewServer
{
public:
WEAVE_ERROR SimpleTest ();
virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, const char * const aTestCaseId)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
WeaveLogDetail(DataManagement, "Test Case ID: %s", aTestCaseId);
//IgnoreUnusedVariable(aExchangeMgr);
//SimpleTest ();
err = aExchangeMgr->RegisterUnsolicitedMessageHandler(nl::Weave::Profiles::kWeaveProfile_WDM, kMsgType_ViewRequest, IncomingViewRequest, this);
SuccessOrExit(err);
exit:
return err;
}
private:
static void IncomingViewRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
uint8_t msgType, PacketBuffer *payload);
};
static MockWdmViewServerImpl gWdmViewServer;
MockWdmViewServer * MockWdmViewServer::GetInstance ()
{
return &gWdmViewServer;
}
void MockWdmViewServerImpl::IncomingViewRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
uint8_t msgType, PacketBuffer *payload)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
PacketBuffer* msgBuf = PacketBuffer::New();
WeaveLogDetail(DataManagement, "Incoming View Request");
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
{
// Schema validation
nl::Weave::TLV::TLVType dummyContainerType;
nl::Weave::TLV::TLVReader ValidationReader;
ValidationReader.Init(payload);
ValidationReader.Next();
err = ValidationReader.EnterContainer(dummyContainerType);
SuccessOrExit(err);
err = ValidationReader.Next();
SuccessOrExit(err);
PathList::Parser paths;
paths.Init(ValidationReader);
WeaveLogError(DataManagement, "CheckSchemaValidity: (0 means good) %" PRIu32, paths.CheckSchemaValidity());
err = ValidationReader.ExitContainer(dummyContainerType);
SuccessOrExit(err);
}
#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY);
{
nl::Weave::TLV::TLVWriter writer;
nl::Weave::TLV::TLVType dummyContainerType;
writer.Init(msgBuf);
err = writer.StartContainer(nl::Weave::TLV::AnonymousTag, nl::Weave::TLV::kTLVType_Structure, dummyContainerType);
SuccessOrExit(err);
DataList::Builder list;
list.Init(&writer, ViewResponse::kCsTag_DataList);
{
DataElement::Builder & builder = list.CreateDataElementBuilder();
builder.LastForCurrentChange(false);
Path::Builder & pathBuilder = builder.CreatePathBuilder();
pathBuilder.ProfileID(0x13)
.ResourceID(0xDEADBEEF)
.InstanceID(0)
.EndOfPath();
if (WEAVE_NO_ERROR != pathBuilder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
nl::Weave::TLV::TLVWriter * dataWriter = builder.GetWriter();
{
nl::Weave::TLV::TLVType type;
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), nl::Weave::TLV::kTLVType_Structure, type);
{
dataWriter->PutString(nl::Weave::TLV::ContextTag(1), "en_gb");
}
dataWriter->EndContainer(type);
}
builder.EndOfDataElement();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "DataElement builder failed");
}
}
{
DataElement::Builder & builder = list.CreateDataElementBuilder();
builder.LastForCurrentChange(false);
Path::Builder & pathBuilder = builder.CreatePathBuilder();
pathBuilder.ProfileID(0x13)
.ResourceID(0xDEADBEEF)
.InstanceID(0)
.TagSection()
.AdditionalTag(nl::Weave::TLV::ContextTag(1))
.EndOfPath();
if (WEAVE_NO_ERROR != pathBuilder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
nl::Weave::TLV::TLVWriter * dataWriter = builder.GetWriter();
dataWriter->PutString(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), "en_us");
builder.EndOfDataElement();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "DataElement builder failed");
}
}
{
DataElement::Builder & builder = list.CreateDataElementBuilder();
builder.LastForCurrentChange(false);
Path::Builder & pathBuilder = builder.CreatePathBuilder();
pathBuilder.ProfileID(0x14)
.ResourceID(0xDEADBEEF)
.InstanceID(0)
.EndOfPath();
if (WEAVE_NO_ERROR != pathBuilder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
nl::Weave::TLV::TLVWriter * dataWriter = builder.GetWriter();
{
nl::Weave::TLV::TLVType type1;
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), nl::Weave::TLV::kTLVType_Structure, type1);
// root
{
nl::Weave::TLV::TLVType type2;
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(1), nl::Weave::TLV::kTLVType_Structure, type2);
// s1
{
nl::Weave::TLV::TLVType type3;
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(1), nl::Weave::TLV::kTLVType_Structure, type3);
// s3
{
// a
uint32_t a = 100;
dataWriter->Put(nl::Weave::TLV::ContextTag(1), a);
// b
bool b = true;
dataWriter->PutBoolean(nl::Weave::TLV::ContextTag(2), b);
// c
char c[] = "hello";
dataWriter->PutString(nl::Weave::TLV::ContextTag(3), c);
}
dataWriter->EndContainer(type3);
// d
int32_t d = -20;
dataWriter->Put(nl::Weave::TLV::ContextTag(2), d);
}
dataWriter->EndContainer(type2);
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(2), nl::Weave::TLV::kTLVType_Structure, type2);
// s2
{
// e
bool e = false;
dataWriter->PutBoolean(nl::Weave::TLV::ContextTag(1), e);
int8_t f = -4;
dataWriter->Put(nl::Weave::TLV::ContextTag(2), f);
int8_t g = -3;
dataWriter->Put(nl::Weave::TLV::ContextTag(3), g);
}
dataWriter->EndContainer(type2);
// h
int32_t h = -700;
dataWriter->Put(nl::Weave::TLV::ContextTag(3), h);
}
dataWriter->EndContainer(type1);
}
builder.EndOfDataElement();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "DataElement builder failed");
}
}
list.EndOfDataList();
if (WEAVE_NO_ERROR != list.GetError())
{
WeaveLogError(DataManagement, "DataList builder failed");
}
err = writer.EndContainer(dummyContainerType);
SuccessOrExit(err);
err = writer.Finalize();
SuccessOrExit(err);
}
err = ec->SendMessage(nl::Weave::Profiles::kWeaveProfile_WDM, kMsgType_ViewResponse, msgBuf, nl::Weave::ExchangeContext::kSendFlag_RequestAck);
msgBuf = NULL;
SuccessOrExit(err);
exit:
WeaveLogFunctError(err);
if (NULL != payload)
{
PacketBuffer::Free(payload);
payload = NULL;
}
if (NULL != msgBuf)
{
PacketBuffer::Free(msgBuf);
msgBuf = NULL;
}
if (NULL != ec)
{
ec->Close();
}
}
WEAVE_ERROR MockWdmViewServerImpl::SimpleTest ()
{
WeaveLogError(DataManagement, "Simple Test");
WeaveLogError(DataManagement, "####################### Path Test #######################");
{
uint8_t buffer[1024] = { 0 };
nl::Weave::TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
Path::Builder builder;
builder.Init(&writer);
builder.ProfileID(0xABCD1234)
.ResourceID(0x12345678)
.InstanceID(0xdeadbeef)
.EndOfPath();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
uint32_t encodedLen = writer.GetLengthWritten();
nl::Weave::TLV::TLVReader reader;
reader.Init(buffer, encodedLen);
reader.Next();
Path::Parser path;
path.Init(reader);
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
WeaveLogError(DataManagement, "CheckSchemaValidity: (0 means good) %" PRIu32, path.CheckSchemaValidity());
#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
uint64_t temp64 = 0;
path.GetResourceID(&temp64);
WeaveLogError(DataManagement, "GetResourceID: 0x%X", temp64);
uint32_t temp32 = 0;
path.GetProfileID(&temp32);
WeaveLogError(DataManagement, "GetProfileID: 0x%X", temp32);
temp64 = 0;
path.GetInstanceID(&temp64);
WeaveLogError(DataManagement, "GetInstanceID: 0x%X", temp64);
}
WeaveLogError(DataManagement, "####################### DataElement Test #######################");
{
uint8_t buffer[1024] = { 0 };
nl::Weave::TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
DataElement::Builder builder;
builder.Init(&writer);
builder.LastForCurrentChange(true);
Path::Builder & pathBuilder = builder.CreatePathBuilder();
pathBuilder.ProfileID(0xABCD1234)
.ResourceID(0x12345678)
.InstanceID(0xdeadbeef)
.TagSection()
.AdditionalTag(nl::Weave::TLV::ProfileTag(0x12345678, 4096))
.AdditionalTag(nl::Weave::TLV::ContextTag(5))
.EndOfPath();
if (WEAVE_NO_ERROR != pathBuilder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
nl::Weave::TLV::TLVWriter * dataWriter = builder.GetWriter();
//dataWriter->Put(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), 4.23f);
nl::Weave::TLV::TLVType tempContainerType;
// TODO: check for error
dataWriter->StartContainer(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), nl::Weave::TLV::kTLVType_Structure, tempContainerType);
dataWriter->ImplicitProfileId = 0xABCD1234;
// TODO: check for error
dataWriter->Put(nl::Weave::TLV::ProfileTag(0xABCD1234, 8), 4.23f);
dataWriter->ImplicitProfileId = nl::Weave::TLV::kProfileIdNotSpecified;
// TODO: check for error
dataWriter->EndContainer(tempContainerType);
builder.EndOfDataElement();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "DataElement builder failed");
}
uint32_t encodedLen = writer.GetLengthWritten();
nl::Weave::TLV::TLVReader reader;
reader.Init(buffer, encodedLen);
reader.Next();
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
DataElement::Parser data;
data.Init(reader);
WeaveLogError(DataManagement, "CheckSchemaValidity: (0 means good) %" PRIu32, data.CheckSchemaValidity());
#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
}
WeaveLogError(DataManagement, "####################### PathList Test #######################");
{
uint8_t buffer[1024] = { 0 };
nl::Weave::TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
PathList::Builder list;
list.Init(&writer, ViewRequest::kCsTag_PathList);
for (unsigned int i = 0; i < 5; ++i)
{
Path::Builder & path = list.CreatePathBuilder();
path.ProfileID(0xABCD1234)
.ResourceID(0x12345678)
.InstanceID(i)
.TagSection();
for (unsigned int j = 0; j < i; ++j)
{
path.AdditionalTag(nl::Weave::TLV::ContextTag(j));
}
path.EndOfPath();
if (WEAVE_NO_ERROR != path.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
}
list.EndOfPathList();
if (WEAVE_NO_ERROR != list.GetError())
{
WeaveLogError(DataManagement, "PathList builder failed");
}
uint32_t encodedLen = writer.GetLengthWritten();
nl::Weave::TLV::TLVReader reader;
reader.Init(buffer, encodedLen);
reader.Next();
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
PathList::Parser paths;
paths.Init(reader);
WeaveLogError(DataManagement, "CheckSchemaValidity: (0 means good) %" PRIu32, paths.CheckSchemaValidity());
#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
}
WeaveLogError(DataManagement, "####################### DataList Test #######################");
{
uint8_t buffer[1024] = { 0 };
nl::Weave::TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
DataList::Builder list;
list.Init(&writer, ViewResponse::kCsTag_DataList);
for (unsigned int i = 0; i < 3; ++i)
{
DataElement::Builder & builder = list.CreateDataElementBuilder();
builder.LastForCurrentChange(true);
Path::Builder & pathBuilder = builder.CreatePathBuilder();
pathBuilder.ProfileID(0xABCD1234)
.ResourceID(0x12345678)
.InstanceID(i)
.TagSection()
.AdditionalTag(nl::Weave::TLV::ProfileTag(0x12345678, 4096))
.AdditionalTag(nl::Weave::TLV::ContextTag(i))
.EndOfPath();
if (WEAVE_NO_ERROR != pathBuilder.GetError())
{
WeaveLogError(DataManagement, "Path builder failed");
}
nl::Weave::TLV::TLVWriter * dataWriter = builder.GetWriter();
dataWriter->Put(nl::Weave::TLV::ContextTag(DataElement::kCsTag_Data), 100 + i);
builder.EndOfDataElement();
if (WEAVE_NO_ERROR != builder.GetError())
{
WeaveLogError(DataManagement, "DataElement builder failed");
}
}
list.EndOfDataList();
if (WEAVE_NO_ERROR != list.GetError())
{
WeaveLogError(DataManagement, "DataList builder failed");
}
uint32_t encodedLen = writer.GetLengthWritten();
nl::Weave::TLV::TLVReader reader;
reader.Init(buffer, encodedLen);
reader.Next();
#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
DataList::Parser data;
data.Init(reader);
WeaveLogError(DataManagement, "CheckSchemaValidity: (0 means good) %" PRIu32, data.CheckSchemaValidity());
#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
}
WeaveLogError(DataManagement, "Simple Test Completed");
return WEAVE_NO_ERROR;
}
#endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
#endif // 0