mirror of
https://github.com/espressif/openthread.git
synced 2026-10-01 21:37:39 +00:00
Some Very Simple Fuzz Testing (#901)
* Add initial 'dump' fuzzing for radio receive.
This commit is contained in:
@@ -163,6 +163,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\tests\unit\test_aes.cpp" />
|
<ClCompile Include="..\..\tests\unit\test_aes.cpp" />
|
||||||
|
<ClCompile Include="..\..\tests\unit\test_fuzz.cpp" />
|
||||||
<ClCompile Include="..\..\tests\unit\test_hmac_sha256.cpp" />
|
<ClCompile Include="..\..\tests\unit\test_hmac_sha256.cpp" />
|
||||||
<ClCompile Include="..\..\tests\unit\test_link_quality.cpp" />
|
<ClCompile Include="..\..\tests\unit\test_link_quality.cpp" />
|
||||||
<ClCompile Include="..\..\tests\unit\test_lowpan.cpp" />
|
<ClCompile Include="..\..\tests\unit\test_lowpan.cpp" />
|
||||||
@@ -177,6 +178,7 @@
|
|||||||
<ClCompile Include="..\..\tests\unit\test_windows.cpp" />
|
<ClCompile Include="..\..\tests\unit\test_windows.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\tests\unit\test_platform.h" />
|
||||||
<ClInclude Include="..\..\tests\unit\test_util.h" />
|
<ClInclude Include="..\..\tests\unit\test_util.h" />
|
||||||
<ClInclude Include="..\..\tests\unit\test_util.hpp" />
|
<ClInclude Include="..\..\tests\unit\test_util.hpp" />
|
||||||
<ClInclude Include="..\..\tests\unit\test_vector.h" />
|
<ClInclude Include="..\..\tests\unit\test_vector.h" />
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
<ClCompile Include="..\..\tests\unit\test_aes.cpp">
|
<ClCompile Include="..\..\tests\unit\test_aes.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\tests\unit\test_fuzz.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\tests\unit\test_hmac_sha256.cpp">
|
<ClCompile Include="..\..\tests\unit\test_hmac_sha256.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -56,6 +59,9 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\tests\unit\test_platform.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\tests\unit\test_util.h">
|
<ClInclude Include="..\..\tests\unit\test_util.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@@ -51,6 +51,10 @@
|
|||||||
(RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \
|
(RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \
|
||||||
TRUE)
|
TRUE)
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define assert(cond) \
|
#define assert(cond) \
|
||||||
|
|||||||
@@ -1154,6 +1154,10 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError)
|
|||||||
mPcapCallback(aFrame, mPcapCallbackContext);
|
mPcapCallback(aFrame, mPcapCallbackContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure we have a valid frame before attempting to read any contents of
|
||||||
|
// the buffer received from the radio.
|
||||||
|
SuccessOrExit(error = aFrame->ValidatePsdu());
|
||||||
|
|
||||||
aFrame->GetSrcAddr(srcaddr);
|
aFrame->GetSrcAddr(srcaddr);
|
||||||
neighbor = mMle.GetNeighbor(srcaddr);
|
neighbor = mMle.GetNeighbor(srcaddr);
|
||||||
|
|
||||||
|
|||||||
+120
-1
@@ -58,7 +58,7 @@ ThreadError Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
|
|||||||
// Sequence Number
|
// Sequence Number
|
||||||
length += kDsnSize;
|
length += kDsnSize;
|
||||||
|
|
||||||
// Destinatino PAN + Address
|
// Destinatinon PAN + Address
|
||||||
switch (aFcf & Frame::kFcfDstAddrMask)
|
switch (aFcf & Frame::kFcfDstAddrMask)
|
||||||
{
|
{
|
||||||
case Frame::kFcfDstAddrNone:
|
case Frame::kFcfDstAddrNone:
|
||||||
@@ -145,6 +145,125 @@ ThreadError Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
|
|||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThreadError Frame::ValidatePsdu(void)
|
||||||
|
{
|
||||||
|
ThreadError error = kThreadError_Parse;
|
||||||
|
uint8_t offset = 0;
|
||||||
|
uint16_t fcf;
|
||||||
|
uint8_t footerLength = kFcsSize;
|
||||||
|
|
||||||
|
VerifyOrExit((offset += kFcfSize + kDsnSize) <= GetPsduLength(),);
|
||||||
|
fcf = static_cast<uint16_t>((GetPsdu()[1] << 8) | GetPsdu()[0]);
|
||||||
|
|
||||||
|
// Destinatinon PAN + Address
|
||||||
|
switch (fcf & Frame::kFcfDstAddrMask)
|
||||||
|
{
|
||||||
|
case Frame::kFcfDstAddrNone:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Frame::kFcfDstAddrShort:
|
||||||
|
offset += sizeof(PanId) + sizeof(ShortAddress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Frame::kFcfDstAddrExt:
|
||||||
|
offset += sizeof(PanId) + sizeof(ExtAddress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Source PAN + Address
|
||||||
|
switch (fcf & Frame::kFcfSrcAddrMask)
|
||||||
|
{
|
||||||
|
case Frame::kFcfSrcAddrNone:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Frame::kFcfSrcAddrShort:
|
||||||
|
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||||
|
{
|
||||||
|
offset += sizeof(PanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += sizeof(ShortAddress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Frame::kFcfSrcAddrExt:
|
||||||
|
if ((fcf & Frame::kFcfPanidCompression) == 0)
|
||||||
|
{
|
||||||
|
offset += sizeof(PanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += sizeof(ExtAddress);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security Header
|
||||||
|
if (fcf & Frame::kFcfSecurityEnabled)
|
||||||
|
{
|
||||||
|
VerifyOrExit(offset <= GetPsduLength(),);
|
||||||
|
uint8_t secControl = GetPsdu()[offset];
|
||||||
|
|
||||||
|
switch (secControl & kKeyIdModeMask)
|
||||||
|
{
|
||||||
|
case kKeyIdMode0:
|
||||||
|
offset += kKeySourceSizeMode0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kKeyIdMode1:
|
||||||
|
offset += kKeySourceSizeMode1 + kKeyIndexSize;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kKeyIdMode2:
|
||||||
|
offset += kKeySourceSizeMode2 + kKeyIndexSize;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kKeyIdMode3:
|
||||||
|
offset += kKeySourceSizeMode3 + kKeyIndexSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (secControl & kSecLevelMask)
|
||||||
|
{
|
||||||
|
case kSecNone:
|
||||||
|
case kSecEnc:
|
||||||
|
footerLength += kMic0Size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kSecMic32:
|
||||||
|
case kSecEncMic32:
|
||||||
|
footerLength += kMic32Size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kSecMic64:
|
||||||
|
case kSecEncMic64:
|
||||||
|
footerLength += kMic64Size;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kSecMic128:
|
||||||
|
case kSecEncMic128:
|
||||||
|
footerLength += kMic128Size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command ID
|
||||||
|
if ((fcf & kFcfFrameTypeMask) == kFcfFrameMacCmd)
|
||||||
|
{
|
||||||
|
offset += kCommandIdSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
VerifyOrExit((offset + footerLength) <= GetPsduLength(),);
|
||||||
|
|
||||||
|
error = kThreadError_None;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Frame::GetType(void)
|
uint8_t Frame::GetType(void)
|
||||||
{
|
{
|
||||||
return GetPsdu()[0] & Frame::kFcfFrameTypeMask;
|
return GetPsdu()[0] & Frame::kFcfFrameTypeMask;
|
||||||
|
|||||||
@@ -251,6 +251,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
ThreadError InitMacHeader(uint16_t aFcf, uint8_t aSecCtl);
|
ThreadError InitMacHeader(uint16_t aFcf, uint8_t aSecCtl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method validates the frame.
|
||||||
|
*
|
||||||
|
* @retval kThreadError_None Successfully parsed the MAC header.
|
||||||
|
* @retval kThreadError_Parse Failed to parse through the MAC header.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ThreadError ValidatePsdu(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the IEEE 802.15.4 Frame Type.
|
* This method returns the IEEE 802.15.4 Frame Type.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ ThreadError Lowpan::CopyContext(const Context &aContext, Ip6::Address &aAddress)
|
|||||||
|
|
||||||
ThreadError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress)
|
ThreadError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress)
|
||||||
{
|
{
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
|
||||||
switch (aMacAddr.mLength)
|
switch (aMacAddr.mLength)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
@@ -79,7 +81,7 @@ ThreadError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aCon
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(false);
|
ExitNow(error = kThreadError_Parse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aContext.mPrefixLength > 64)
|
if (aContext.mPrefixLength > 64)
|
||||||
@@ -91,7 +93,8 @@ ThreadError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return kThreadError_None;
|
exit:
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Lowpan::CompressSourceIid(const Mac::Address &aMacAddr, const Ip6::Address &aIpAddr, const Context &aContext,
|
int Lowpan::CompressSourceIid(const Mac::Address &aMacAddr, const Ip6::Address &aIpAddr, const Context &aContext,
|
||||||
@@ -716,7 +719,7 @@ int Lowpan::DecompressBaseHeader(Ip6::Header &ip6Header, const Mac::Address &aMa
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kHcDstAddrMode3:
|
case kHcDstAddrMode3:
|
||||||
ComputeIid(aMacDest, dstContext, ip6Header.GetDestination());
|
SuccessOrExit(error = ComputeIid(aMacDest, dstContext, ip6Header.GetDestination()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -946,6 +949,8 @@ int Lowpan::Decompress(Message &aMessage, const Mac::Address &aMacSource, const
|
|||||||
uint16_t compressedLength = 0;
|
uint16_t compressedLength = 0;
|
||||||
uint16_t currentOffset = aMessage.GetOffset();
|
uint16_t currentOffset = aMessage.GetOffset();
|
||||||
|
|
||||||
|
VerifyOrExit(aBufLen >= 2, error = kThreadError_Parse);
|
||||||
|
|
||||||
compressed = (((static_cast<uint16_t>(cur[0]) << 8) | cur[1]) & kHcNextHeader) != 0;
|
compressed = (((static_cast<uint16_t>(cur[0]) << 8) | cur[1]) & kHcNextHeader) != 0;
|
||||||
|
|
||||||
VerifyOrExit((rval = DecompressBaseHeader(ip6Header, aMacSource, aMacDest, aBuf)) >= 0,
|
VerifyOrExit((rval = DecompressBaseHeader(ip6Header, aMacSource, aMacDest, aBuf)) >= 0,
|
||||||
|
|||||||
@@ -1413,15 +1413,18 @@ void MeshForwarder::HandleReceivedFrame(Mac::Frame &aFrame)
|
|||||||
switch (aFrame.GetType())
|
switch (aFrame.GetType())
|
||||||
{
|
{
|
||||||
case Mac::Frame::kFcfFrameData:
|
case Mac::Frame::kFcfFrameData:
|
||||||
if (reinterpret_cast<Lowpan::MeshHeader *>(payload)->IsMeshHeader())
|
if (payloadLength >= sizeof(Lowpan::MeshHeader) &&
|
||||||
|
reinterpret_cast<Lowpan::MeshHeader *>(payload)->IsMeshHeader())
|
||||||
{
|
{
|
||||||
HandleMesh(payload, payloadLength, messageInfo);
|
HandleMesh(payload, payloadLength, messageInfo);
|
||||||
}
|
}
|
||||||
else if (reinterpret_cast<Lowpan::FragmentHeader *>(payload)->IsFragmentHeader())
|
else if (payloadLength >= sizeof(Lowpan::FragmentHeader) &&
|
||||||
|
reinterpret_cast<Lowpan::FragmentHeader *>(payload)->IsFragmentHeader())
|
||||||
{
|
{
|
||||||
HandleFragment(payload, payloadLength, macSource, macDest, messageInfo);
|
HandleFragment(payload, payloadLength, macSource, macDest, messageInfo);
|
||||||
}
|
}
|
||||||
else if (Lowpan::Lowpan::IsLowpanHc(payload))
|
else if (payloadLength >= 1 &&
|
||||||
|
Lowpan::Lowpan::IsLowpanHc(payload))
|
||||||
{
|
{
|
||||||
HandleLowpanHC(payload, payloadLength, macSource, macDest, messageInfo);
|
HandleLowpanHC(payload, payloadLength, macSource, macDest, messageInfo);
|
||||||
}
|
}
|
||||||
@@ -1564,6 +1567,8 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
|||||||
aFrame += headerLength;
|
aFrame += headerLength;
|
||||||
aFrameLength -= static_cast<uint8_t>(headerLength);
|
aFrameLength -= static_cast<uint8_t>(headerLength);
|
||||||
|
|
||||||
|
VerifyOrExit(datagramLength >= message->GetOffset() + aFrameLength, error = kThreadError_Parse);
|
||||||
|
|
||||||
SuccessOrExit(error = message->SetLength(datagramLength));
|
SuccessOrExit(error = message->SetLength(datagramLength));
|
||||||
|
|
||||||
message->SetDatagramTag(datagramTag);
|
message->SetDatagramTag(datagramTag);
|
||||||
@@ -1718,7 +1723,7 @@ void MeshForwarder::HandleDataRequest(const Mac::Address &aMacSource, const Thre
|
|||||||
// Security Check: only process secure Data Poll frames.
|
// Security Check: only process secure Data Poll frames.
|
||||||
VerifyOrExit(aMessageInfo.mLinkSecurity, ;);
|
VerifyOrExit(aMessageInfo.mLinkSecurity, ;);
|
||||||
|
|
||||||
assert(mMle.GetDeviceState() != Mle::kDeviceStateDetached);
|
VerifyOrExit(mMle.GetDeviceState() != Mle::kDeviceStateDetached, ;);
|
||||||
|
|
||||||
VerifyOrExit((child = mMle.GetChild(aMacSource)) != NULL, ;);
|
VerifyOrExit((child = mMle.GetChild(aMacSource)) != NULL, ;);
|
||||||
child->mLastHeard = Timer::GetNow();
|
child->mLastHeard = Timer::GetNow();
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
|||||||
# since they are not part of the package.
|
# since they are not part of the package.
|
||||||
#
|
#
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
|
test_platform.h \
|
||||||
test_util.h \
|
test_util.h \
|
||||||
test_util.hpp \
|
test_util.hpp \
|
||||||
test_vector.h \
|
test_vector.h \
|
||||||
@@ -73,6 +74,7 @@ endif # OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
|
|||||||
|
|
||||||
check_PROGRAMS = \
|
check_PROGRAMS = \
|
||||||
test-aes \
|
test-aes \
|
||||||
|
test-fuzz \
|
||||||
test-hmac-sha256 \
|
test-hmac-sha256 \
|
||||||
test-lowpan \
|
test-lowpan \
|
||||||
test-link-quality \
|
test-link-quality \
|
||||||
@@ -118,6 +120,9 @@ TESTS_ENVIRONMENT = \
|
|||||||
test_aes_LDADD = $(COMMON_LDADD)
|
test_aes_LDADD = $(COMMON_LDADD)
|
||||||
test_aes_SOURCES = test_platform.cpp test_aes.cpp
|
test_aes_SOURCES = test_platform.cpp test_aes.cpp
|
||||||
|
|
||||||
|
test_fuzz_LDADD = $(COMMON_LDADD)
|
||||||
|
test_fuzz_SOURCES = test_platform.cpp test_fuzz.cpp
|
||||||
|
|
||||||
test_hmac_sha256_LDADD = $(COMMON_LDADD)
|
test_hmac_sha256_LDADD = $(COMMON_LDADD)
|
||||||
test_hmac_sha256_SOURCES = test_platform.cpp test_hmac_sha256.cpp
|
test_hmac_sha256_SOURCES = test_platform.cpp test_hmac_sha256.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, The OpenThread Authors.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holder nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_platform.h"
|
||||||
|
//#include <mac/mac_frame.hpp>
|
||||||
|
|
||||||
|
//#define DBG_FUZZ 1
|
||||||
|
|
||||||
|
bool g_fRadioEnabled = false;
|
||||||
|
uint8_t g_RecvChannel = 0;
|
||||||
|
uint8_t g_TransmitPsdu[128];
|
||||||
|
RadioPacket g_TransmitRadioPacket;
|
||||||
|
bool g_fTransmit = false;
|
||||||
|
|
||||||
|
ThreadError testFuzzRadioEnable(otInstance *)
|
||||||
|
{
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("Radio enabled");
|
||||||
|
#endif
|
||||||
|
g_fRadioEnabled = true;
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError testFuzzRadioDisable(otInstance *)
|
||||||
|
{
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("Radio disabled");
|
||||||
|
#endif
|
||||||
|
g_fRadioEnabled = false;
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError testFuzzRadioReceive(otInstance *, uint8_t aChannel)
|
||||||
|
{
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("==> receive");
|
||||||
|
#endif
|
||||||
|
g_RecvChannel = aChannel;
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError testFuzzRadioTransmit(otInstance *)
|
||||||
|
{
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("==> transmit");
|
||||||
|
#endif
|
||||||
|
g_fTransmit = true;
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioPacket *testFuzztRadioGetTransmitBuffer(otInstance *)
|
||||||
|
{
|
||||||
|
return &g_TransmitRadioPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestFuzz(uint32_t aSeconds)
|
||||||
|
{
|
||||||
|
// Set the radio capabilities to disable any Mac related timer dependencies
|
||||||
|
g_testPlatRadioCaps = (otRadioCaps)(kRadioCapsAckTimeout | kRadioCapsTransmitRetries);
|
||||||
|
|
||||||
|
// Set the platform function pointers
|
||||||
|
g_TransmitRadioPacket.mPsdu = g_TransmitPsdu;
|
||||||
|
g_testPlatRadioEnable = testFuzzRadioEnable;
|
||||||
|
g_testPlatRadioDisable = testFuzzRadioDisable;
|
||||||
|
g_testPlatRadioReceive = testFuzzRadioReceive;
|
||||||
|
g_testPlatRadioTransmit = testFuzzRadioTransmit;
|
||||||
|
g_testPlatRadioGetTransmitBuffer = testFuzztRadioGetTransmitBuffer;
|
||||||
|
|
||||||
|
// Initialize our timing variables
|
||||||
|
uint32_t tStart = otPlatAlarmGetNow();
|
||||||
|
uint32_t tEnd = tStart + (aSeconds * 1000);
|
||||||
|
|
||||||
|
otInstance *aInstance;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
uint32_t seed = (uint32_t)time(NULL);
|
||||||
|
srand(seed);
|
||||||
|
Log("Initialized seed = 0x%X", seed);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPENTHREAD_MULTIPLE_INSTANCE
|
||||||
|
uint64_t otInstanceBufferLength = 0;
|
||||||
|
uint8_t *otInstanceBuffer = NULL;
|
||||||
|
|
||||||
|
// Call to query the buffer size
|
||||||
|
(void)otInstanceInit(NULL, &otInstanceBufferLength);
|
||||||
|
|
||||||
|
// Call to allocate the buffer
|
||||||
|
otInstanceBuffer = (uint8_t *)malloc(otInstanceBufferLength);
|
||||||
|
VerifyOrQuit(otInstanceBuffer != NULL, "Failed to allocate otInstance");
|
||||||
|
memset(&otInstanceBuffer, 0, otInstanceBufferLength);
|
||||||
|
|
||||||
|
// Initialize Openthread with the buffer
|
||||||
|
aInstance = otInstanceInit(otInstanceBuffer, &otInstanceBufferLength);
|
||||||
|
#else
|
||||||
|
aInstance = otInstanceInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VerifyOrQuit(aInstance != NULL, "Failed to initialize otInstance");
|
||||||
|
|
||||||
|
// Start the Thread network
|
||||||
|
otSetPanId(aInstance, (otPanId)0xFACE);
|
||||||
|
otInterfaceUp(aInstance);
|
||||||
|
otThreadStart(aInstance);
|
||||||
|
|
||||||
|
uint32_t countRecv = 0;
|
||||||
|
|
||||||
|
while (otPlatAlarmGetNow() < tEnd)
|
||||||
|
{
|
||||||
|
otProcessQueuedTasklets(aInstance);
|
||||||
|
|
||||||
|
if (g_testPlatAlarmSet && otPlatAlarmGetNow() >= g_testPlatAlarmNext)
|
||||||
|
{
|
||||||
|
g_testPlatAlarmSet = false;
|
||||||
|
otPlatAlarmFired(aInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_fRadioEnabled)
|
||||||
|
{
|
||||||
|
if (g_fTransmit)
|
||||||
|
{
|
||||||
|
g_fTransmit = false;
|
||||||
|
otPlatRadioTransmitDone(aInstance, true, kThreadError_None);
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("<== transmit");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_RecvChannel != 0)
|
||||||
|
{
|
||||||
|
uint8_t fuzzRecvBuff[128];
|
||||||
|
RadioPacket fuzzPacket;
|
||||||
|
|
||||||
|
// Initialize the radio packet with a random length
|
||||||
|
memset(&fuzzPacket, 0, sizeof(fuzzPacket));
|
||||||
|
fuzzPacket.mPsdu = fuzzRecvBuff;
|
||||||
|
fuzzPacket.mChannel = g_RecvChannel;
|
||||||
|
fuzzPacket.mLength = (uint8_t)(otPlatRandomGet() % 127);
|
||||||
|
|
||||||
|
// Populate the length with random
|
||||||
|
for (uint8_t i = 0; i < fuzzPacket.mLength; i++)
|
||||||
|
{
|
||||||
|
fuzzRecvBuff[i] = (uint8_t)otPlatRandomGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the global flag
|
||||||
|
g_RecvChannel = 0;
|
||||||
|
|
||||||
|
// Indicate the receive complete
|
||||||
|
otPlatRadioReceiveDone(aInstance, &fuzzPacket, kThreadError_None);
|
||||||
|
|
||||||
|
countRecv++;
|
||||||
|
#ifdef DBG_FUZZ
|
||||||
|
Log("<== receive (%llu, %u bytes)", countRecv, fuzzPacket.mLength);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Hack to get a receive poll immediately
|
||||||
|
otSetChannel(aInstance, 11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log("%u packets received", countRecv);
|
||||||
|
|
||||||
|
// Clean up the instance
|
||||||
|
otInstanceFinalize(aInstance);
|
||||||
|
|
||||||
|
#ifdef OPENTHREAD_MULTIPLE_INSTANCE
|
||||||
|
free(otInstanceBuffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_TEST_MAIN
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
TestFuzz(0); // For the time being, don't actually fuzz, just validate we can start and clean up
|
||||||
|
printf("All tests passed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+131
-48
@@ -26,38 +26,54 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "test_platform.h"
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
__forceinline int gettimeofday(struct timeval *tv, struct timezone *)
|
||||||
#include <windows.h>
|
{
|
||||||
|
DWORD tick = GetTickCount();
|
||||||
|
tv->tv_sec = (long)(tick / 1000);
|
||||||
|
tv->tv_usec = (long)(tick * 1000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <openthread.h>
|
bool g_testPlatAlarmSet = false;
|
||||||
|
uint32_t g_testPlatAlarmNext = 0;
|
||||||
|
testPlatAlarmStop g_testPlatAlarmStop = NULL;
|
||||||
|
testPlatAlarmStartAt g_testPlatAlarmStartAt = NULL;
|
||||||
|
testPlatAlarmGetNow g_testPlatAlarmGetNow = NULL;
|
||||||
|
|
||||||
#include <common/code_utils.hpp>
|
otRadioCaps g_testPlatRadioCaps = kRadioCapsNone;
|
||||||
#include <platform/alarm.h>
|
testPlatRadioSetPanId g_testPlatRadioSetPanId = NULL;
|
||||||
#include <platform/logging.h>
|
testPlatRadioSetExtendedAddress g_testPlatRadioSetExtendedAddress = NULL;
|
||||||
#include <platform/misc.h>
|
testPlatRadioEnable g_testPlatRadioEnable = NULL;
|
||||||
#include <platform/radio.h>
|
testPlatRadioDisable g_testPlatRadioDisable = NULL;
|
||||||
#include <platform/random.h>
|
testPlatRadioSetShortAddress g_testPlatRadioSetShortAddress = NULL;
|
||||||
|
testPlatRadioReceive g_testPlatRadioReceive = NULL;
|
||||||
|
testPlatRadioTransmit g_testPlatRadioTransmit = NULL;
|
||||||
|
testPlatRadioGetTransmitBuffer g_testPlatRadioGetTransmitBuffer = NULL;
|
||||||
|
|
||||||
#include <stdio.h>
|
void testPlatResetToDefaults(void)
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
{
|
||||||
kCallCountIndexAlarmStop = 0,
|
g_testPlatAlarmSet = false;
|
||||||
kCallCountIndexAlarmStart,
|
g_testPlatAlarmNext = 0;
|
||||||
kCallCountIndexTimerHandler,
|
g_testPlatAlarmStop = NULL;
|
||||||
|
g_testPlatAlarmStartAt = NULL;
|
||||||
|
g_testPlatAlarmGetNow = NULL;
|
||||||
|
|
||||||
kCallCountIndexMax
|
g_testPlatRadioCaps = kRadioCapsNone;
|
||||||
};
|
g_testPlatRadioSetPanId = NULL;
|
||||||
|
g_testPlatRadioSetExtendedAddress = NULL;
|
||||||
uint32_t sNow;
|
g_testPlatRadioSetShortAddress = NULL;
|
||||||
uint32_t sPlatT0;
|
g_testPlatRadioEnable = NULL;
|
||||||
uint32_t sPlatDt;
|
g_testPlatRadioDisable = NULL;
|
||||||
bool sTimerOn;
|
g_testPlatRadioReceive = NULL;
|
||||||
uint32_t sCallCount[kCallCountIndexMax];
|
g_testPlatRadioTransmit = NULL;
|
||||||
|
g_testPlatRadioGetTransmitBuffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool sDiagMode = false;
|
bool sDiagMode = false;
|
||||||
|
|
||||||
@@ -71,23 +87,43 @@ extern "C" {
|
|||||||
// Alarm
|
// Alarm
|
||||||
//
|
//
|
||||||
|
|
||||||
void otPlatAlarmStop(otInstance *)
|
void otPlatAlarmStop(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
sTimerOn = false;
|
if (g_testPlatAlarmStop)
|
||||||
sCallCount[kCallCountIndexAlarmStop]++;
|
{
|
||||||
|
g_testPlatAlarmStop(aInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_testPlatAlarmSet = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void otPlatAlarmStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
|
void otPlatAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||||
{
|
{
|
||||||
sTimerOn = true;
|
if (g_testPlatAlarmStartAt)
|
||||||
sCallCount[kCallCountIndexAlarmStart]++;
|
{
|
||||||
sPlatT0 = aT0;
|
g_testPlatAlarmStartAt(aInstance, aT0, aDt);
|
||||||
sPlatDt = aDt;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_testPlatAlarmSet = true;
|
||||||
|
g_testPlatAlarmNext = aT0 + aDt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t otPlatAlarmGetNow(void)
|
uint32_t otPlatAlarmGetNow(void)
|
||||||
{
|
{
|
||||||
return sNow;
|
if (g_testPlatAlarmGetNow)
|
||||||
|
{
|
||||||
|
return g_testPlatAlarmGetNow();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (uint32_t)((tv.tv_sec * 1000) + (tv.tv_usec / 1000) + 123456);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -98,30 +134,56 @@ extern "C" {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void otPlatRadioSetPanId(otInstance *, uint16_t)
|
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
|
||||||
{
|
{
|
||||||
|
if (g_testPlatRadioSetPanId)
|
||||||
|
{
|
||||||
|
g_testPlatRadioSetPanId(aInstance, aPanId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void otPlatRadioSetExtendedAddress(otInstance *, uint8_t *)
|
void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *aExtAddr)
|
||||||
{
|
{
|
||||||
|
if (g_testPlatRadioSetExtendedAddress)
|
||||||
|
{
|
||||||
|
g_testPlatRadioSetExtendedAddress(aInstance, aExtAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void otPlatRadioSetShortAddress(otInstance *, uint16_t)
|
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddr)
|
||||||
{
|
{
|
||||||
|
if (g_testPlatRadioSetShortAddress)
|
||||||
|
{
|
||||||
|
g_testPlatRadioSetShortAddress(aInstance, aShortAddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void otPlatRadioSetPromiscuous(otInstance *, bool)
|
void otPlatRadioSetPromiscuous(otInstance *, bool)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError otPlatRadioEnable(otInstance *)
|
ThreadError otPlatRadioEnable(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
return kThreadError_None;
|
if (g_testPlatRadioEnable)
|
||||||
|
{
|
||||||
|
return g_testPlatRadioEnable(aInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError otPlatRadioDisable(otInstance *)
|
ThreadError otPlatRadioDisable(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
return kThreadError_None;
|
if (g_testPlatRadioEnable)
|
||||||
|
{
|
||||||
|
return g_testPlatRadioDisable(aInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError otPlatRadioSleep(otInstance *)
|
ThreadError otPlatRadioSleep(otInstance *)
|
||||||
@@ -129,19 +191,40 @@ extern "C" {
|
|||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError otPlatRadioReceive(otInstance *, uint8_t)
|
ThreadError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
|
||||||
{
|
{
|
||||||
return kThreadError_None;
|
if (g_testPlatRadioReceive)
|
||||||
|
{
|
||||||
|
return g_testPlatRadioReceive(aInstance, aChannel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError otPlatRadioTransmit(otInstance *)
|
ThreadError otPlatRadioTransmit(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
return kThreadError_None;
|
if (g_testPlatRadioTransmit)
|
||||||
|
{
|
||||||
|
return g_testPlatRadioTransmit(aInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return kThreadError_None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *)
|
RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
|
||||||
{
|
{
|
||||||
return (RadioPacket *)0;
|
if (g_testPlatRadioGetTransmitBuffer)
|
||||||
|
{
|
||||||
|
return g_testPlatRadioGetTransmitBuffer(aInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (RadioPacket *)0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t otPlatRadioGetRssi(otInstance *)
|
int8_t otPlatRadioGetRssi(otInstance *)
|
||||||
@@ -151,7 +234,7 @@ extern "C" {
|
|||||||
|
|
||||||
otRadioCaps otPlatRadioGetCaps(otInstance *)
|
otRadioCaps otPlatRadioGetCaps(otInstance *)
|
||||||
{
|
{
|
||||||
return kRadioCapsNone;
|
return g_testPlatRadioCaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool otPlatRadioGetPromiscuous(otInstance *)
|
bool otPlatRadioGetPromiscuous(otInstance *)
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, The OpenThread Authors.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holder nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TEST_PLATFORM_H
|
||||||
|
#define TEST_PLATFORM_H
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#include <windows.h>
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <openthread.h>
|
||||||
|
#include <openthread-tasklet.h>
|
||||||
|
|
||||||
|
#include <common/code_utils.hpp>
|
||||||
|
#include <platform/alarm.h>
|
||||||
|
#include <platform/logging.h>
|
||||||
|
#include <platform/misc.h>
|
||||||
|
#include <platform/radio.h>
|
||||||
|
#include <platform/random.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "test_util.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Alarm Platform
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef void (*testPlatAlarmStop)(otInstance *);
|
||||||
|
typedef void (*testPlatAlarmStartAt)(otInstance *, uint32_t, uint32_t);
|
||||||
|
typedef uint32_t (*testPlatAlarmGetNow)(void);
|
||||||
|
|
||||||
|
extern bool g_testPlatAlarmSet;
|
||||||
|
extern uint32_t g_testPlatAlarmNext;
|
||||||
|
extern testPlatAlarmStop g_testPlatAlarmStop;
|
||||||
|
extern testPlatAlarmStartAt g_testPlatAlarmStartAt;
|
||||||
|
extern testPlatAlarmGetNow g_testPlatAlarmGetNow;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Radio Platform
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef void (*testPlatRadioSetPanId)(otInstance *, uint16_t);
|
||||||
|
typedef void (*testPlatRadioSetExtendedAddress)(otInstance *, uint8_t *);
|
||||||
|
typedef void (*testPlatRadioSetShortAddress)(otInstance *, uint16_t);
|
||||||
|
|
||||||
|
typedef ThreadError(*testPlatRadioEnable)(otInstance *);
|
||||||
|
typedef ThreadError(*testPlatRadioDisable)(otInstance *);
|
||||||
|
typedef ThreadError(*testPlatRadioReceive)(otInstance *, uint8_t);
|
||||||
|
typedef ThreadError(*testPlatRadioTransmit)(otInstance *);
|
||||||
|
typedef RadioPacket *(*testPlatRadioGetTransmitBuffer)(otInstance *);
|
||||||
|
|
||||||
|
extern otRadioCaps g_testPlatRadioCaps;
|
||||||
|
extern testPlatRadioSetPanId g_testPlatRadioSetPanId;
|
||||||
|
extern testPlatRadioSetExtendedAddress g_testPlatRadioSetExtendedAddress;
|
||||||
|
extern testPlatRadioSetShortAddress g_testPlatRadioSetShortAddress;
|
||||||
|
extern testPlatRadioEnable g_testPlatRadioEnable;
|
||||||
|
extern testPlatRadioDisable g_testPlatRadioDisable;
|
||||||
|
extern testPlatRadioReceive g_testPlatRadioReceive;
|
||||||
|
extern testPlatRadioTransmit g_testPlatRadioTransmit;
|
||||||
|
extern testPlatRadioGetTransmitBuffer g_testPlatRadioGetTransmitBuffer;
|
||||||
|
|
||||||
|
// Resets platform functions to defaults
|
||||||
|
void testPlatResetToDefaults(void);
|
||||||
|
|
||||||
|
#endif // TEST_PLATFORM_H
|
||||||
@@ -26,12 +26,9 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test_util.h"
|
#include "test_platform.h"
|
||||||
#include <openthread.h>
|
|
||||||
#include <common/debug.hpp>
|
#include <common/debug.hpp>
|
||||||
#include <common/timer.hpp>
|
#include <common/timer.hpp>
|
||||||
#include <platform/alarm.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <openthread-instance.h>
|
#include <openthread-instance.h>
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@@ -43,11 +40,37 @@ enum
|
|||||||
kCallCountIndexMax
|
kCallCountIndexMax
|
||||||
};
|
};
|
||||||
|
|
||||||
extern uint32_t sNow;
|
uint32_t sNow;
|
||||||
extern uint32_t sPlatT0;
|
uint32_t sPlatT0;
|
||||||
extern uint32_t sPlatDt;
|
uint32_t sPlatDt;
|
||||||
extern bool sTimerOn;
|
bool sTimerOn;
|
||||||
extern uint32_t sCallCount[kCallCountIndexMax];
|
uint32_t sCallCount[kCallCountIndexMax];
|
||||||
|
|
||||||
|
void testTimerAlarmStop(otInstance *)
|
||||||
|
{
|
||||||
|
sTimerOn = false;
|
||||||
|
sCallCount[kCallCountIndexAlarmStop]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testTimerAlarmStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
|
||||||
|
{
|
||||||
|
sTimerOn = true;
|
||||||
|
sCallCount[kCallCountIndexAlarmStart]++;
|
||||||
|
sPlatT0 = aT0;
|
||||||
|
sPlatDt = aDt;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t testTimerAlarmGetNow(void)
|
||||||
|
{
|
||||||
|
return sNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitTestTimer(void)
|
||||||
|
{
|
||||||
|
g_testPlatAlarmStop = testTimerAlarmStop;
|
||||||
|
g_testPlatAlarmStartAt = testTimerAlarmStartAt;
|
||||||
|
g_testPlatAlarmGetNow = testTimerAlarmGetNow;
|
||||||
|
}
|
||||||
|
|
||||||
void InitCounters(void)
|
void InitCounters(void)
|
||||||
{
|
{
|
||||||
@@ -76,6 +99,7 @@ int TestOneTimer(void)
|
|||||||
|
|
||||||
// Test one Timer basic operation.
|
// Test one Timer basic operation.
|
||||||
|
|
||||||
|
InitTestTimer();
|
||||||
InitCounters();
|
InitCounters();
|
||||||
|
|
||||||
sNow = kTimeT0;
|
sNow = kTimeT0;
|
||||||
@@ -321,6 +345,7 @@ int TestTenTimers(void)
|
|||||||
|
|
||||||
// Start the Ten timers.
|
// Start the Ten timers.
|
||||||
|
|
||||||
|
InitTestTimer();
|
||||||
InitCounters();
|
InitCounters();
|
||||||
|
|
||||||
for (i = 0; i < kNumTimers ; i++)
|
for (i = 0; i < kNumTimers ; i++)
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ extern "C" {
|
|||||||
//
|
//
|
||||||
#define CompileTimeAssert(COND, MSG)
|
#define CompileTimeAssert(COND, MSG)
|
||||||
|
|
||||||
|
#define Log(aFormat, ...) printf(aFormat "\n", ## __VA_ARGS__)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -81,12 +83,17 @@ extern "C" {
|
|||||||
typedef void (*utAssertTrue)(bool condition, const wchar_t *message);
|
typedef void (*utAssertTrue)(bool condition, const wchar_t *message);
|
||||||
extern utAssertTrue s_AssertTrue;
|
extern utAssertTrue s_AssertTrue;
|
||||||
|
|
||||||
|
typedef void (*utLogMessage)(const char *format, ...);
|
||||||
|
extern utLogMessage s_LogMessage;
|
||||||
|
|
||||||
#define SuccessOrQuit(ERR, MSG) s_AssertTrue((ERR) == kThreadError_None, L##MSG)
|
#define SuccessOrQuit(ERR, MSG) s_AssertTrue((ERR) == kThreadError_None, L##MSG)
|
||||||
|
|
||||||
#define VerifyOrQuit(ERR, MSG) s_AssertTrue(ERR, L##MSG)
|
#define VerifyOrQuit(ERR, MSG) s_AssertTrue(ERR, L##MSG)
|
||||||
|
|
||||||
#define CompileTimeAssert(COND, MSG) static_assert(COND, MSG)
|
#define CompileTimeAssert(COND, MSG) static_assert(COND, MSG)
|
||||||
|
|
||||||
|
#define Log(aFormat, ...) s_LogMessage(aFormat, ## __VA_ARGS__)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <SDKDDKVer.h>
|
#include <SDKDDKVer.h>
|
||||||
#include "CppUnitTest.h"
|
#include "CppUnitTest.h"
|
||||||
#include "test_util.h"
|
#include "test_util.h"
|
||||||
|
#include "test_platform.h"
|
||||||
|
|
||||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
|
||||||
@@ -80,17 +81,21 @@ void test_packed2();
|
|||||||
void test_packed_union();
|
void test_packed_union();
|
||||||
void test_packed_enum();
|
void test_packed_enum();
|
||||||
|
|
||||||
|
// test_fuzz.cpp
|
||||||
|
void TestFuzz(uint32_t aSeconds);
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
utAssertTrue s_AssertTrue;
|
utAssertTrue s_AssertTrue;
|
||||||
|
utLogMessage s_LogMessage;
|
||||||
|
|
||||||
namespace Thread
|
namespace Thread
|
||||||
{
|
{
|
||||||
TEST_CLASS(UnitTests)
|
TEST_CLASS(UnitTests)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UnitTests() { s_AssertTrue = AssertTrue; }
|
UnitTests() { s_AssertTrue = AssertTrue; s_LogMessage = LogMessage; }
|
||||||
|
|
||||||
// Helper for openthread test code to call
|
// Helper for openthread test code to call
|
||||||
static void AssertTrue(bool condition, const wchar_t* message)
|
static void AssertTrue(bool condition, const wchar_t* message)
|
||||||
@@ -98,6 +103,25 @@ namespace Thread
|
|||||||
Assert::IsTrue(condition, message);
|
Assert::IsTrue(condition, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper for logging a message
|
||||||
|
static void LogMessage(const char* format, ...)
|
||||||
|
{
|
||||||
|
char message[512];
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(message, sizeof(message), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
Logger::WriteMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure to reset the test platform functions before each test
|
||||||
|
TEST_METHOD_INITIALIZE(TestMethodInit)
|
||||||
|
{
|
||||||
|
testPlatResetToDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
// test_aes.cpp
|
// test_aes.cpp
|
||||||
TEST_METHOD(TestMacBeaconFrame) { ::TestMacBeaconFrame(); }
|
TEST_METHOD(TestMacBeaconFrame) { ::TestMacBeaconFrame(); }
|
||||||
TEST_METHOD(TestMacDataFrame) { ::TestMacDataFrame(); }
|
TEST_METHOD(TestMacDataFrame) { ::TestMacDataFrame(); }
|
||||||
@@ -131,5 +155,8 @@ namespace Thread
|
|||||||
TEST_METHOD(test_packed2) { ::test_packed2(); }
|
TEST_METHOD(test_packed2) { ::test_packed2(); }
|
||||||
TEST_METHOD(test_packed_union) { ::test_packed_union(); }
|
TEST_METHOD(test_packed_union) { ::test_packed_union(); }
|
||||||
TEST_METHOD(test_packed_enum) { ::test_packed_enum(); }
|
TEST_METHOD(test_packed_enum) { ::test_packed_enum(); }
|
||||||
};
|
|
||||||
|
// test_settings.cpp
|
||||||
|
TEST_METHOD(RunTestFuzz) { ::TestFuzz(0); }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user