Add Thread Certification 9.2.7 to automated test. (#750)

This commit is contained in:
Jonathan Hui
2016-10-05 10:02:08 -07:00
committed by GitHub
parent e673479eba
commit c24b7cfaed
9 changed files with 435 additions and 89 deletions
+1 -1
View File
@@ -1011,7 +1011,7 @@ void Interpreter::ProcessPanId(int argc, char *argv[])
if (argc == 0)
{
sServer->OutputFormat("%d\r\n", otGetPanId(mInstance));
sServer->OutputFormat("%04x\r\n", otGetPanId(mInstance));
}
else
{
+26
View File
@@ -406,6 +406,32 @@ void Dataset::SetTimestamp(const Timestamp &aTimestamp)
Set(timestampTlv.tlv);
}
int Dataset::Compare(const Dataset &aCompare) const
{
const Timestamp *thisTimestamp = GetTimestamp();
const Timestamp *compareTimestamp = aCompare.GetTimestamp();
int rval;
if (compareTimestamp == NULL && thisTimestamp == NULL)
{
rval = 0;
}
else if (compareTimestamp == NULL && thisTimestamp != NULL)
{
rval = -1;
}
else if (compareTimestamp != NULL && thisTimestamp == NULL)
{
rval = 1;
}
else
{
rval = thisTimestamp->Compare(*compareTimestamp);
}
return rval;
}
ThreadError Dataset::Set(const Tlv &aTlv)
{
ThreadError error = kThreadError_None;
+12
View File
@@ -116,6 +116,18 @@ public:
*/
void SetTimestamp(const Timestamp &aTimestamp);
/**
* This method compares this dataset to another based on the timestamp.
*
* @param[in] aCompare A reference to the timestamp to compare.
*
* @retval -1 if @p aCompare is older than this dataset.
* @retval 0 if @p aCompare is equal to this dataset.
* @retval 1 if @p aCompare is newer than this dataset.
*
*/
int Compare(const Dataset &aCompare) const;
/**
* This method sets a TLV in the Dataset.
*
+147 -69
View File
@@ -58,32 +58,17 @@ DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType,
const char *aUriGet):
mLocal(aType),
mNetwork(aType),
mCoapServer(aThreadNetif.GetCoapServer()),
mMle(aThreadNetif.GetMle()),
mNetif(aThreadNetif),
mNetworkDataLeader(aThreadNetif.GetNetworkDataLeader()),
mResourceSet(aUriSet, &DatasetManager::HandleSet, this),
mResourceGet(aUriGet, &DatasetManager::HandleGet, this),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &DatasetManager::HandleTimer, this),
mSocket(aThreadNetif.GetIp6().mUdp),
mUriSet(aUriSet),
mUriGet(aUriGet),
mCoapServer(aThreadNetif.GetCoapServer())
mUriGet(aUriGet)
{
}
void DatasetManager::StartLeader(void)
{
mNetwork = mLocal;
mCoapServer.AddResource(mResourceSet);
mCoapServer.AddResource(mResourceGet);
}
void DatasetManager::StopLeader(void)
{
mCoapServer.RemoveResource(mResourceSet);
mCoapServer.RemoveResource(mResourceGet);
}
ThreadError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &aFlags)
{
ThreadError error = kThreadError_None;
@@ -113,6 +98,13 @@ exit:
return error;
}
ThreadError DatasetManager::Clear(uint8_t &aFlags)
{
mNetwork.Clear();
HandleNetworkUpdate(aFlags);
return kThreadError_None;
}
ThreadError DatasetManager::Set(const Dataset &aDataset, uint8_t &aFlags)
{
mNetwork.Set(aDataset);
@@ -135,18 +127,10 @@ exit:
void DatasetManager::HandleNetworkUpdate(uint8_t &aFlags)
{
const Timestamp *localTimestamp;
const Timestamp *networkTimestamp;
int compare;
int compare = mLocal.Compare(mNetwork);
aFlags = kFlagNetworkUpdated;
networkTimestamp = mNetwork.GetTimestamp();
assert(networkTimestamp != NULL);
localTimestamp = mLocal.GetTimestamp();
compare = (localTimestamp == NULL) ? 1 : localTimestamp->Compare(*networkTimestamp);
if (compare > 0)
{
mLocal = mNetwork;
@@ -165,9 +149,9 @@ void DatasetManager::HandleTimer(void *aContext)
void DatasetManager::HandleTimer(void)
{
VerifyOrExit(mMle.IsAttached() && ((mNetwork.GetTimestamp() == NULL) ||
(mLocal.GetTimestamp() && mNetwork.GetTimestamp()->Compare(*mLocal.GetTimestamp()) > 0)), ;);
VerifyOrExit(mLocal.Get(Tlv::kDelayTimer) != NULL, ;);
VerifyOrExit(mMle.IsAttached(),);
VerifyOrExit(mLocal.Compare(mNetwork) < 0,);
Register();
mTimer.Start(1000);
@@ -199,6 +183,12 @@ ThreadError DatasetManager::Register(void)
header.AppendUriPathOptions(mUriSet);
header.Finalize();
if (strcmp(mUriSet, OPENTHREAD_URI_PENDING_SET) == 0)
{
PendingDataset *pending = static_cast<PendingDataset *>(this);
pending->UpdateDelayTimer();
}
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
SuccessOrExit(error = message->Append(mLocal.GetBytes(), mLocal.GetSize()));
@@ -246,13 +236,31 @@ exit:
return;
}
void DatasetManager::HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
void DatasetManager::Get(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
static_cast<DatasetManager *>(aContext)->HandleSet(aHeader, aMessage, aMessageInfo);
Tlv tlv;
uint16_t offset = aMessage.GetOffset();
uint8_t tlvs[Dataset::kMaxSize];
uint8_t length = 0;
while (offset < aMessage.GetLength())
{
aMessage.Read(offset, sizeof(tlv), &tlv);
if (tlv.GetType() == Tlv::kGet)
{
length = tlv.GetLength();
aMessage.Read(offset + sizeof(Tlv), length, tlvs);
break;
}
offset += sizeof(tlv) + tlv.GetLength();
}
SendGetResponse(aHeader, aMessageInfo, tlvs, length);
}
void DatasetManager::HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Tlv tlv;
Timestamp timestamp;
@@ -355,37 +363,7 @@ exit:
SendSetResponse(aHeader, aMessageInfo, state);
}
return;
}
void DatasetManager::HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
static_cast<DatasetManager *>(aContext)->HandleGet(aHeader, aMessage, aMessageInfo);
}
void DatasetManager::HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Tlv tlv;
uint16_t offset = aMessage.GetOffset();
uint8_t tlvs[Dataset::kMaxSize];
uint8_t length = 0;
while (offset < aMessage.GetLength())
{
aMessage.Read(offset, sizeof(tlv), &tlv);
if (tlv.GetType() == Tlv::kGet)
{
length = tlv.GetLength();
aMessage.Read(offset + sizeof(Tlv), length, tlvs);
break;
}
offset += sizeof(tlv) + tlv.GetLength();
}
SendGetResponse(aHeader, aMessageInfo, tlvs, length);
return state == StateTlv::kAccept ? kThreadError_None : kThreadError_Drop;
}
ThreadError DatasetManager::SendSetRequest(const otOperationalDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength)
@@ -639,10 +617,36 @@ exit:
}
ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif):
DatasetManager(aThreadNetif, Tlv::kActiveTimestamp, OPENTHREAD_URI_ACTIVE_SET, OPENTHREAD_URI_ACTIVE_GET)
DatasetManager(aThreadNetif, Tlv::kActiveTimestamp, OPENTHREAD_URI_ACTIVE_SET, OPENTHREAD_URI_ACTIVE_GET),
mResourceGet(OPENTHREAD_URI_ACTIVE_GET, &ActiveDataset::HandleGet, this),
mResourceSet(OPENTHREAD_URI_ACTIVE_SET, &ActiveDataset::HandleSet, this)
{
}
void ActiveDataset::StartLeader(void)
{
mNetwork = mLocal;
mCoapServer.AddResource(mResourceGet);
mCoapServer.AddResource(mResourceSet);
}
void ActiveDataset::StopLeader(void)
{
mCoapServer.RemoveResource(mResourceGet);
mCoapServer.RemoveResource(mResourceSet);
}
ThreadError ActiveDataset::Clear(void)
{
ThreadError error = kThreadError_None;
uint8_t flags;
SuccessOrExit(error = DatasetManager::Clear(flags));
exit:
return error;
}
ThreadError ActiveDataset::Set(const otOperationalDataset &aDataset)
{
ThreadError error = kThreadError_None;
@@ -680,6 +684,32 @@ exit:
return error;
}
void ActiveDataset::HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
static_cast<ActiveDataset *>(aContext)->HandleGet(aHeader, aMessage, aMessageInfo);
}
void ActiveDataset::HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
DatasetManager::Get(aHeader, aMessage, aMessageInfo);
}
void ActiveDataset::HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
static_cast<ActiveDataset *>(aContext)->HandleSet(aHeader, aMessage, aMessageInfo);
}
void ActiveDataset::HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
SuccessOrExit(DatasetManager::Set(aHeader, aMessage, aMessageInfo));
ApplyConfiguration();
exit:
return;
}
ThreadError ActiveDataset::ApplyConfiguration(void)
{
ThreadError error = kThreadError_None;
@@ -755,10 +785,38 @@ ThreadError ActiveDataset::ApplyConfiguration(void)
PendingDataset::PendingDataset(ThreadNetif &aThreadNetif):
DatasetManager(aThreadNetif, Tlv::kPendingTimestamp, OPENTHREAD_URI_PENDING_SET, OPENTHREAD_URI_PENDING_GET),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, PendingDataset::HandleTimer, this)
mResourceGet(OPENTHREAD_URI_PENDING_GET, &PendingDataset::HandleGet, this),
mResourceSet(OPENTHREAD_URI_PENDING_SET, &PendingDataset::HandleSet, this),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &PendingDataset::HandleTimer, this)
{
}
void PendingDataset::StartLeader(void)
{
mNetwork = mLocal;
mNetworkTime = mLocalTime;
mCoapServer.AddResource(mResourceGet);
mCoapServer.AddResource(mResourceSet);
}
void PendingDataset::StopLeader(void)
{
mCoapServer.RemoveResource(mResourceGet);
mCoapServer.RemoveResource(mResourceSet);
}
ThreadError PendingDataset::Clear(void)
{
ThreadError error = kThreadError_None;
uint8_t flags;
SuccessOrExit(error = DatasetManager::Clear(flags));
ResetDelayTimer(flags);
exit:
return error;
}
ThreadError PendingDataset::Set(const otOperationalDataset &aDataset)
{
ThreadError error = kThreadError_None;
@@ -784,10 +842,30 @@ exit:
return error;
}
void PendingDataset::StartLeader(void)
void PendingDataset::HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
DatasetManager::StartLeader();
mNetworkTime = mLocalTime;
static_cast<PendingDataset *>(aContext)->HandleGet(aHeader, aMessage, aMessageInfo);
}
void PendingDataset::HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
DatasetManager::Get(aHeader, aMessage, aMessageInfo);
}
void PendingDataset::HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
static_cast<PendingDataset *>(aContext)->HandleSet(aHeader, aMessage, aMessageInfo);
}
void PendingDataset::HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
SuccessOrExit(DatasetManager::Set(aHeader, aMessage, aMessageInfo));
ResetDelayTimer(kFlagLocalUpdated | kFlagNetworkUpdated);
exit:
return;
}
void PendingDataset::ResetDelayTimer(uint8_t aFlags)
+40 -15
View File
@@ -53,9 +53,6 @@ namespace MeshCoP {
class DatasetManager
{
public:
void StartLeader(void);
void StopLeader(void);
Dataset &GetLocal(void) { return mLocal; }
Dataset &GetNetwork(void) { return mNetwork; }
@@ -71,6 +68,8 @@ protected:
DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType, const char *aUriSet, const char *aUriGet);
ThreadError Clear(uint8_t &aFlags);
ThreadError Set(const otOperationalDataset &aDataset, uint8_t &aFlags);
ThreadError Set(const Dataset &aDataset, uint8_t &aFlags);
@@ -78,9 +77,14 @@ protected:
ThreadError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength,
uint8_t &aFlags);
void Get(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
ThreadError Set(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Dataset mLocal;
Dataset mNetwork;
Coap::Server &mCoapServer;
Mle::Mle &mMle;
ThreadNetif &mNetif;
NetworkData::Leader &mNetworkDataLeader;
@@ -89,14 +93,6 @@ private:
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleTimer(void *aContext);
void HandleTimer(void);
@@ -107,8 +103,6 @@ private:
void SendGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
uint8_t *aTlvs, uint8_t aLength);
Coap::Resource mResourceSet;
Coap::Resource mResourceGet;
Timer mTimer;
Ip6::UdpSocket mSocket;
@@ -117,8 +111,6 @@ private:
const char *mUriSet;
const char *mUriGet;
Coap::Server &mCoapServer;
};
class ActiveDataset: public DatasetManager
@@ -126,6 +118,12 @@ class ActiveDataset: public DatasetManager
public:
ActiveDataset(ThreadNetif &aThreadNetif);
void StartLeader(void);
void StopLeader(void);
ThreadError Clear(void);
ThreadError Set(const otOperationalDataset &aDataset);
ThreadError Set(const Dataset &aDataset);
@@ -133,6 +131,18 @@ public:
ThreadError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
ThreadError ApplyConfiguration(void);
private:
static void HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Coap::Resource mResourceGet;
Coap::Resource mResourceSet;
};
class PendingDataset: public DatasetManager
@@ -142,6 +152,10 @@ public:
void StartLeader(void);
void StopLeader(void);
ThreadError Clear(void);
ThreadError Set(const otOperationalDataset &aDataset);
ThreadError Set(const Timestamp &aTimestamp, const Message &aMessage, uint16_t aOffset, uint8_t aLength);
@@ -149,12 +163,23 @@ public:
void UpdateDelayTimer(void);
private:
static void HandleGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleTimer(void *aContext);
void HandleTimer(void);
void ResetDelayTimer(uint8_t aFlags);
void UpdateDelayTimer(Dataset &aDataset, uint32_t &aStartTime);
Coap::Resource mResourceGet;
Coap::Resource mResourceSet;
Timer mTimer;
uint32_t mLocalTime;
uint32_t mNetworkTime;
+10 -2
View File
@@ -1853,7 +1853,7 @@ ThreadError Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageI
}
else
{
mNetif.GetActiveDataset().GetNetwork().Clear();
mNetif.GetActiveDataset().Clear();
}
// Pending Dataset
@@ -1864,7 +1864,7 @@ ThreadError Mle::HandleDataResponse(const Message &aMessage, const Ip6::MessageI
}
else
{
mNetif.GetPendingDataset().GetNetwork().Clear();
mNetif.GetPendingDataset().Clear();
}
mRetrieveNewNetworkData = false;
@@ -2102,6 +2102,10 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
mNetif.GetActiveDataset().Set(activeTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength());
}
}
else
{
mNetif.GetActiveDataset().Clear();
}
// Pending Timestamp
if (Tlv::GetTlv(aMessage, Tlv::kPendingTimestamp, sizeof(pendingTimestamp), pendingTimestamp) == kThreadError_None)
@@ -2115,6 +2119,10 @@ ThreadError Mle::HandleChildIdResponse(const Message &aMessage, const Ip6::Messa
mNetif.GetPendingDataset().Set(pendingTimestamp, aMessage, offset + sizeof(tlv), tlv.GetLength());
}
}
else
{
mNetif.GetPendingDataset().Clear();
}
// Parent Attach Success
mParentRequestTimer.Stop();
+3
View File
@@ -104,6 +104,7 @@ EXTRA_DIST = \
thread-cert/Cert_7_1_05_BorderRouterAsRouter.py \
thread-cert/Cert_8_1_01_Commissioning.py \
thread-cert/Cert_8_1_02_Commissioning.py \
thread-cert/Cert_9_2_07_DelayTimer.py \
thread-cert/Cert_9_2_12_Announce.py \
thread-cert/Cert_9_2_13_EnergyScan.py \
thread-cert/Cert_9_2_14_PanIdQuery.py \
@@ -223,6 +224,7 @@ check_SCRIPTS += \
thread-cert/Cert_7_1_05_BorderRouterAsRouter.py \
thread-cert/Cert_8_1_01_Commissioning.py \
thread-cert/Cert_8_1_02_Commissioning.py \
thread-cert/Cert_9_2_07_DelayTimer.py \
thread-cert/Cert_9_2_12_Announce.py \
thread-cert/Cert_9_2_13_EnergyScan.py \
thread-cert/Cert_9_2_14_PanIdQuery.py \
@@ -244,6 +246,7 @@ TESTS = \
XFAIL_NCP_TESTS = \
thread-cert/Cert_8_1_01_Commissioning.py \
thread-cert/Cert_8_1_02_Commissioning.py \
thread-cert/Cert_9_2_07_DelayTimer.py \
thread-cert/Cert_9_2_12_Announce.py \
thread-cert/Cert_9_2_13_EnergyScan.py \
thread-cert/Cert_9_2_14_PanIdQuery.py \
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/python
#
# 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.
#
import time
import unittest
import node
PANID_INIT = 0xface
COMMISSIONER = 1
LEADER = 2
ROUTER = 3
LEADER_ACTIVE_TIMESTAMP = 10
ROUTER_ACTIVE_TIMESTAMP = 20
ROUTER_PENDING_TIMESTAMP = 30
ROUTER_PENDING_ACTIVE_TIMESTAMP = 21
COMMISSIONER_PENDING_CHANNEL = 2
COMMISSIONER_PENDING_PANID = 0xafce
class Cert_9_2_7_DelayTimer(unittest.TestCase):
def setUp(self):
self.nodes = {}
for i in range(1,4):
self.nodes[i] = node.Node(i)
self.nodes[COMMISSIONER].set_panid(PANID_INIT)
self.nodes[COMMISSIONER].set_mode('rsdn')
self.nodes[COMMISSIONER].add_whitelist(self.nodes[LEADER].get_addr64())
self.nodes[COMMISSIONER].enable_whitelist()
self.nodes[COMMISSIONER].set_router_selection_jitter(1)
self.nodes[LEADER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP)
self.nodes[LEADER].set_panid(PANID_INIT)
self.nodes[LEADER].set_mode('rsdn')
self.nodes[LEADER].set_partition_id(0xffffffff)
self.nodes[LEADER].add_whitelist(self.nodes[COMMISSIONER].get_addr64())
self.nodes[LEADER].enable_whitelist()
self.nodes[LEADER].set_router_selection_jitter(1)
self.nodes[ROUTER].set_active_dataset(ROUTER_ACTIVE_TIMESTAMP)
self.nodes[ROUTER].set_pending_dataset(ROUTER_PENDING_TIMESTAMP, ROUTER_PENDING_ACTIVE_TIMESTAMP)
self.nodes[ROUTER].set_panid(PANID_INIT)
self.nodes[ROUTER].set_mode('rsdn')
self.nodes[ROUTER].set_partition_id(0)
self.nodes[ROUTER].enable_whitelist()
self.nodes[ROUTER].set_router_selection_jitter(1)
def tearDown(self):
for node in list(self.nodes.values()):
node.stop()
del self.nodes
def test(self):
self.nodes[LEADER].start()
self.nodes[LEADER].set_state('leader')
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
self.nodes[COMMISSIONER].start()
time.sleep(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
self.nodes[ROUTER].start()
time.sleep(5)
self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')
self.nodes[LEADER].add_whitelist(self.nodes[ROUTER].get_addr64())
self.nodes[ROUTER].add_whitelist(self.nodes[LEADER].get_addr64())
time.sleep(30)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
self.nodes[COMMISSIONER].send_mgmt_pending_set(pending_timestamp=40,
active_timestamp=80,
delay_timer=10000,
channel=COMMISSIONER_PENDING_CHANNEL,
panid=COMMISSIONER_PENDING_PANID)
time.sleep(20)
self.assertEqual(self.nodes[LEADER].get_panid(), COMMISSIONER_PENDING_PANID)
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), COMMISSIONER_PENDING_PANID)
self.assertEqual(self.nodes[ROUTER].get_panid(), COMMISSIONER_PENDING_PANID)
self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
self.assertEqual(self.nodes[COMMISSIONER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
self.assertEqual(self.nodes[ROUTER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
ipaddrs = self.nodes[ROUTER].get_addrs()
for ipaddr in ipaddrs:
if ipaddr[0:4] != 'fe80':
break
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
if __name__ == '__main__':
unittest.main()
+71 -2
View File
@@ -215,6 +215,14 @@ class Node:
self.pexpect.expect('Done')
return addr
def get_channel(self):
self.send_command('channel')
i = self.pexpect.expect('(\d+)\r\n')
if i == 0:
channel = int(self.pexpect.match.groups()[0])
self.pexpect.expect('Done')
return channel
def set_channel(self, channel):
cmd = 'channel %d' % channel
self.send_command(cmd)
@@ -258,16 +266,30 @@ class Node:
def get_panid(self):
self.send_command('panid')
i = self.pexpect.expect('([0-9a-fA-F]{16})')
i = self.pexpect.expect('([0-9a-fA-F]{4})')
if i == 0:
panid = self.pexpect.match.groups()[0]
panid = int(self.pexpect.match.groups()[0], 16)
self.pexpect.expect('Done')
return panid
def set_panid(self, panid):
cmd = 'panid %d' % panid
self.send_command(cmd)
self.pexpect.expect('Done')
def get_partition_id(self):
self.send_command('leaderpartitionid')
i = self.pexpect.expect('(\d+)\r\n')
if i == 0:
weight = self.pexpect.match.groups()[0]
self.pexpect.expect('Done')
return weight
def set_partition_id(self, partition_id):
cmd = 'leaderpartitionid %d' % partition_id
self.send_command(cmd)
self.pexpect.expect('Done')
def set_router_upgrade_threshold(self, threshold):
cmd = 'routerupgradethreshold %d' % threshold
self.send_command(cmd)
@@ -446,10 +468,57 @@ class Node:
self.send_command('dataset commit active')
self.pexpect.expect('Done')
def set_pending_dataset(self, pendingtimestamp, activetimestamp, panid=None, channel=None):
self.send_command('dataset clear')
self.pexpect.expect('Done')
cmd = 'dataset pendingtimestamp %d' % pendingtimestamp
self.send_command(cmd)
self.pexpect.expect('Done')
cmd = 'dataset activetimestamp %d' % activetimestamp
self.send_command(cmd)
self.pexpect.expect('Done')
if panid != None:
cmd = 'dataset panid %d' % panid
self.send_command(cmd)
self.pexpect.expect('Done')
if channel != None:
cmd = 'dataset channel %d' % channel
self.send_command(cmd)
self.pexpect.expect('Done')
self.send_command('dataset commit pending')
self.pexpect.expect('Done')
def announce_begin(self, mask, count, period, ipaddr):
cmd = 'commissioner announce ' + str(mask) + ' ' + str(count) + ' ' + str(period) + ' ' + ipaddr
self.send_command(cmd)
self.pexpect.expect('Done')
def send_mgmt_pending_set(self, pending_timestamp=None, active_timestamp=None, delay_timer=None, channel=None,
panid=None):
cmd = 'dataset mgmtsetcommand pending '
if pending_timestamp != None:
cmd += 'pendingtimestamp %d ' % pending_timestamp
if active_timestamp != None:
cmd += 'activetimestamp %d ' % active_timestamp
if delay_timer != None:
cmd += 'delaytimer %d ' % delay_timer
if channel != None:
cmd += 'channel %d ' % channel
if panid != None:
cmd += 'panid %d ' % panid
self.send_command(cmd)
self.pexpect.expect('Done')
if __name__ == '__main__':
unittest.main()