def setup_method(self, method): # Create NodeConfig instance self.nodeConfig = NodeConfig(configFilePath) if method.__name__ != "test_init": self.nodeParams = NodeParams(config=self.nodeConfig) # Create NodeParams instance
def __init__(self, configFile=[], config=[]): if configFile: self.config = NodeConfig(configFile) elif config: self.config = config self.setupParams()
def test_protobufConversion(self): """Tests conversion between json and protobuf configuration representations.""" # Convert json data to protobuf format with open (configFilePath, "r") as jsonFile: configData = json.load(jsonFile) #protobuf = self.nodeConfig.toProtoBuf(configData) protobuf = NodeConfig.toProtoBuf(configData) # Convert back to json representation #fromProtobuf = self.nodeConfig.fromProtoBuf(protobuf.SerializeToString()) fromProtobuf = NodeConfig.fromProtoBuf(protobuf.SerializeToString()) # Hash config instance from conversion and compare to initial configuration nc_protobuf = NodeConfig(configData=fromProtobuf) assert(self.nodeConfig.calculateHash() == nc_protobuf.calculateHash())
def loadConfig(self, newConfig, hashValue): '''Verify and queue new configuration for loading.''' # Convert from protobuf to json jsonConfig = NodeConfig.fromProtoBuf(newConfig) jsonConfig['node'][ 'nodeId'] = self.config.nodeId # Don't overwrite node id via update # Create, verify, and store new configuration newConfig = NodeConfig(configData=jsonConfig) if (newConfig.calculateHash() == hashValue and newConfig.loadSuccess): # configuration verified #self.newConfig = newConfig return [True, newConfig] else: #self.newConfig = None return [False, None]
def setup_method(self, method): # Populate truth data #self.configTruthData = json.load(open(configFilePath)) ### Update truth data to match expected node configuration output #self.configTruthData.update({'nodeId': 0}) # TDMA comm test #if method.__name__ == 'test_TDMACommConfigLoad': # self.configTruthData['commType'] = 'TDMA' # Create node config json input file #with open(testConfigFilePath, 'w') as outfile: # json.dump(self.configTruthData, outfile) # Create NodeConfig instance self.nodeConfig = NodeConfig(configFilePath)
def test_loadConfig(self): """Test loadConfig method of NodeParams.""" # Create new config for update newConfig = NodeConfig(configFilePath) newConfigHash = newConfig.calculateHash() with open(configFilePath, "r") as jsonFile: configData = json.load(jsonFile) newConfig_pb = NodeConfig.toProtoBuf(configData).SerializeToString() # Test update method badHash = hashlib.sha1() assert (self.nodeParams.loadConfig(newConfig_pb, badHash) == False ) # test rejection with bad hash assert (self.nodeParams.newConfig == None) assert (self.nodeParams.loadConfig(newConfig_pb, newConfigHash) == True ) # test acceptance assert (self.nodeParams.newConfig != None)
def test_updateConfig(self): """Test updateConfig method of NodeParams.""" # Load valid new config newConfig = NodeConfig(configFilePath) newConfigHash = newConfig.calculateHash() with open(configFilePath, "r") as jsonFile: configData = json.load(jsonFile) newConfig_pb = NodeConfig.toProtoBuf(configData).SerializeToString() self.nodeParams.loadConfig(newConfig_pb, newConfigHash) # Test successful loading self.nodeParams.config.FCBaudrate = newConfig.FCBaudrate / 2.0 # change a parameter to verify loading of new config assert (self.nodeParams.config.FCBaudrate != newConfig.FCBaudrate) assert (self.nodeParams.updateConfig() == True) assert (self.nodeParams.config.FCBaudrate == newConfig.FCBaudrate) assert (self.nodeParams.newConfig == None) # Expect no load when config missing assert (self.nodeParams.updateConfig() == False)
def __init__(self, configFile=[], config=[]): if configFile: self.config = NodeConfig(configFile) elif config: self.config = config # Configuration update holder self.newConfig = None # Mesh status self.restartTime = None self.restartRequested = False self.restartConfirmed = False self.setupParams()
def initMesh(self, currentTime=time.time()): """Initialize node mesh networks.""" # Create tdma comm messages flooredStartTime = math.floor(self.commStartTime) self.tdmaCmds[TDMACmds['MeshStatus']] = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': int(flooredStartTime), 'status': self.tdmaStatus, 'configHash': self.nodeParams.config.calculateHash()}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['statusTxInterval']) self.tdmaCmds[TDMACmds['LinkStatus']] = Command(TDMACmds['LinkStatus'], {'linkStatus': self.nodeParams.linkStatus, 'nodeId': self.nodeParams.config.nodeId}, [TDMACmds['LinkStatus'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['linksTxInterval']) if self.nodeParams.config.nodeId != 0: # stop ground node from broadcasting time offset self.tdmaCmds[TDMACmds['TimeOffset']] = Command(TDMACmds['TimeOffset'], {'nodeStatus': self.nodeParams.nodeStatus[self.nodeParams.config.nodeId-1]}, [TDMACmds['TimeOffset'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['offsetTxInterval']) # Current network configuration message self.initialConfigTxTime = self.commStartTime + self.nodeParams.config.nodeId * self.nodeParams.config.commConfig['configTxInterval'] configHash = self.nodeParams.config.calculateHash() config_pb = NodeConfig.toProtoBuf(self.nodeParams.config.rawConfig).SerializeToString() self.tdmaCmds[TDMACmds['CurrentConfig']] = Command(TDMACmds['CurrentConfig'], {'config': config_pb, 'configLength': len(config_pb), 'configHash': configHash, 'hashLength': self.nodeParams.config.hashSize}, [TDMACmds['CurrentConfig'], self.nodeParams.config.nodeId], self.maxNumSlots * self.nodeParams.config.commConfig['configTxInterval']) # Determine where in frame mesh network currently is self.syncTDMAFrame(currentTime) self.inited = True print("Node " + str(self.nodeParams.config.nodeId) + " - Initializing comm")
testCmds.update({cmdId: cmd}) # TDMACmds['LinkStatus'] cmdId = TDMACmds['LinkStatus'] linkStatus = [[LinkStatus.NoLink for i in range(nodeParams.config.maxNumNodes)] for j in range(nodeParams.config.maxNumNodes)] linkStatus[nodeId-1] = [LinkStatus.IndirectLink]*nodeParams.config.maxNumNodes cmdData = {'linkStatus': linkStatus, 'nodeId': 1} cmd = Command(cmdId, cmdData, [cmdId, nodeId]) testCmds.update({cmdId: cmd}) # TDMACmds['ConfigUpdate'] cmdId = TDMACmds['ConfigUpdate'] configHash = nodeParams.config.calculateHash() with open(configFilePath, "r") as jsonFile: configData = json.load(jsonFile) newConfig_pb = NodeConfig.toProtoBuf(configData).SerializeToString() cmdData = {'destId': nodeParams.config.nodeId, 'config': newConfig_pb, 'configHash': configHash, 'hashLength': nodeParams.config.hashSize, 'configLength': len(newConfig_pb)} cmd = Command(cmdId, cmdData, [cmdId, nodeId, nodeParams.get_cmdCounter()]) testCmds.update({cmdId: cmd}) # TDMACmds['NetworkRestart'] cmdId = TDMACmds['NetworkRestart'] destId = 4 restartTime = int(time.time() + 1000) cmdData = {'destId': destId, 'restartTime': restartTime} cmd = Command(cmdId, cmdData, [cmdId, nodeId, nodeParams.get_cmdCounter()]) testCmds.update({cmdId: cmd}) ### GndCmds # GndCmds['TimeOffsetSummary'] cmdId = GndCmds['TimeOffsetSummary']
def test_calculateHash(self): """Test calculateHash method of NodeConfig.""" # Verify that hash value does not change when unique parameters are different nodeConfig = NodeConfig(noNodeConfigFilePath) assert(nodeConfig.calculateHash() == self.nodeConfig.calculateHash())
def test_readNodeId(self): """Test proper call of readNodeId method of NodeConfig.""" nodeConfig = NodeConfig(noNodeConfigFilePath) assert(nodeConfig.nodeId == 1) # defaults to node 1 when no nodeId provided
def test_missingConfigEntry(self): """Test for missing configuration entry in configuration file.""" with pytest.raises(KeyError) as e: nodeConfig = NodeConfig(badConfigFilePath) pass
def test_invalidFileLoad(self): """Test for failed load due to bad configuration file.""" with pytest.raises(customExceptions.NodeConfigFileError) as e: nodeConfig = NodeConfig("invalidFile")
def test_noFileLoad(self): """Test for failed load of configuration due to no file provided.""" nodeConfig = NodeConfig("") assert(nodeConfig.nodeId == -1) assert(nodeConfig.loadSuccess == False)
class TestNodeConfig: def setup_method(self, method): # Populate truth data self.configTruthData = json.load(open(configFilePath)) ### Update truth data to match expected node configuration output self.configTruthData.update({'nodeId': 0}) # TDMA comm test if method.__name__ == 'test_TDMACommConfigLoad': self.configTruthData['commType'] = 'TDMA' # Create node config json input file with open(testConfigFilePath, 'w') as outfile: json.dump(self.configTruthData, outfile) # Create NodeConfig instance self.nodeConfig = NodeConfig(testConfigFilePath) def test_standardConfigLoad(self): """Test that standard generic configuration loaded properly.""" print("Testing generic configuration loading") # Test that standar parameters are present self.checkConfigEntries(standardParams, True) def test_tdmaConfigLoad(self): """Test that TDMA comm configuration loaded properly.""" print("Testing TDMA comm configuration loading.") if (self.nodeConfig.commType == "TDMA"): commEntries = [ "preTxGuardLength", "postTxGuardLength", "txLength", "rxLength", "slotLength", "cycleLength", "frameLength", "transmitSlot", "desiredDataRate", "maxNumSlots", "offsetTimeout", "initSyncBound", "operateSyncBound" ] # Check for TDMA config assert (type(self.nodeConfig.commConfig == dict)) self.checkConfigEntries(commEntries, True, list(self.nodeConfig.commConfig.keys())) def test_readNodeId(self): if isBeaglebone(): # only run test if running on node assert (socket.gethostname() == 'node' + str(self.nodeConfig.nodeId)) # confirm hostname assert (netifaces.ifaddresses('eth0')[netifaces.AF_INET][0]['addr'] == '192.168.0.' + str(self.nodeConfig.nodeId) + '0') def test_calculateHash(self): pass def test_hashElem(self): """Test hashElem function to ensure proper handling of all data types.""" import hashlib ### Test hashing of floats testFloat1 = 51.1234567 testFloat2 = 51.12345674 testFloat3 = 51.12345676 testInt1 = 51 testHash1 = hashlib.sha1() testHash2 = hashlib.sha1() print(('%.*f' % (7, testFloat2)).encode('utf-8')) print(('%.*f' % (7, testFloat3)).encode('utf-8')) # Test proper truncation of floats self.nodeConfig.hashElem(testHash1, testFloat1) self.nodeConfig.hashElem(testHash2, testFloat2) hash1Value = testHash1.digest() hash2Value = testHash2.digest() assert (hash1Value == hash2Value) # Test float round down testHash2 = hashlib.sha1() self.nodeConfig.hashElem(testHash2, testFloat3) hash2Value = testHash2.digest() assert (hash1Value != hash2Value) # Test float round up # Test hashing of ints vs floats testHash2 = hashlib.sha1() self.nodeConfig.hashElem(testHash2, testInt1) hash2Value = testHash2.digest() assert (hash1Value != hash2Value) # Test float not truncated def checkConfigEntries(self, testEntries, testCondition, configEntries=None): if configEntries == None: configEntries = list(self.nodeConfig.__dict__.keys()) print("Test Entries:", testEntries) print("Config Entries:", configEntries) for key in testEntries: # Check if key in configuration print("Testing " + str(key) + " in " + str(configEntries)) assert ((key in configEntries) == testCondition) ## Check for any subkeys #if list(testEntries[i]): # Check if entry is a list of entries # for subkey in testEntries[i]: # print(eval('self.nodeConfig.' + entries[i]), truthEntries[i]) # assert (subkey in eval('self.nodeConfig.' + key) == testCondition) def updateTestNodeConfigData(self, platform): """Update appropriate config data prior to testing.""" configTruthData['platform'] = platform
class TestNodeConfig: def setup_method(self, method): # Populate truth data #self.configTruthData = json.load(open(configFilePath)) ### Update truth data to match expected node configuration output #self.configTruthData.update({'nodeId': 0}) # TDMA comm test #if method.__name__ == 'test_TDMACommConfigLoad': # self.configTruthData['commType'] = 'TDMA' # Create node config json input file #with open(testConfigFilePath, 'w') as outfile: # json.dump(self.configTruthData, outfile) # Create NodeConfig instance self.nodeConfig = NodeConfig(configFilePath) def test_noFileLoad(self): """Test for failed load of configuration due to no file provided.""" nodeConfig = NodeConfig("") assert(nodeConfig.nodeId == -1) assert(nodeConfig.loadSuccess == False) def test_invalidFileLoad(self): """Test for failed load due to bad configuration file.""" with pytest.raises(customExceptions.NodeConfigFileError) as e: nodeConfig = NodeConfig("invalidFile") def test_standardConfigLoad(self): """Test that standard generic configuration loaded properly.""" print("Testing generic configuration loading") # Test that standard parameters are present self.checkConfigEntries(standardParams, True) def test_tdmaConfigLoad(self): """Test that TDMA comm configuration loaded properly.""" print("Testing TDMA comm configuration loading.") if (self.nodeConfig.commType == "TDMA"): commEntries = ["preTxGuardLength", "postTxGuardLength", "txLength", "rxLength", "slotLength", "cycleLength", "frameLength", "transmitSlot", "desiredDataRate", "maxNumSlots", "offsetTimeout", "offsetTxInterval", "statusTxInterval", "linksTxInterval", "maxTxBlockSize", "blockTxRequestTimeout", "minBlockTxDelay", "fpga", "initSyncBound", "initTimeToWait", "operateSyncBound"] # Check for TDMA config assert(type(self.nodeConfig.commConfig == dict)) self.checkConfigEntries(commEntries, True, list(self.nodeConfig.commConfig.keys())) # Check FPGA config specific parameters if (self.nodeConfig.commConfig['fpga'] == True): fpgaParams = ["fpgaFailsafePin", "fpgaFifoSize"] self.checkConfigEntries(commEntries, True, list(self.nodeConfig.commConfig.keys())) def test_missingConfigEntry(self): """Test for missing configuration entry in configuration file.""" with pytest.raises(KeyError) as e: nodeConfig = NodeConfig(badConfigFilePath) pass def test_readNodeId(self): """Test proper call of readNodeId method of NodeConfig.""" nodeConfig = NodeConfig(noNodeConfigFilePath) assert(nodeConfig.nodeId == 1) # defaults to node 1 when no nodeId provided def test_updateParameter(self): """Test updateParameter method of NodeConfig.""" # Test attempted update of invalid parameter assert(self.nodeConfig.updateParameter("BadParam", 1) == False) # Test successful update assert(self.nodeConfig.parseMsgMax != 500) assert(self.nodeConfig.updateParameter(ParamId.parseMsgMax, 500)) assert(self.nodeConfig.parseMsgMax == 500) def test_calculateHash(self): """Test calculateHash method of NodeConfig.""" # Verify that hash value does not change when unique parameters are different nodeConfig = NodeConfig(noNodeConfigFilePath) assert(nodeConfig.calculateHash() == self.nodeConfig.calculateHash()) def test_hashElem(self): """Test hashElem function to ensure proper handling of all data types.""" import hashlib ### Test hashing of floats testFloat1 = 51.1234567 testFloat2 = 51.12345674 testFloat3 = 51.12345676 testInt1 = 51 testHash1 = hashlib.sha1() testHash2 = hashlib.sha1() # Test proper truncation of floats self.nodeConfig.hashElem(testHash1, testFloat1) self.nodeConfig.hashElem(testHash2, testFloat2) hash1Value = testHash1.digest() hash2Value = testHash2.digest() assert(hash1Value == hash2Value) # Test float round down testHash2 = hashlib.sha1() self.nodeConfig.hashElem(testHash2, testFloat3) hash2Value = testHash2.digest() assert(hash1Value != hash2Value) # Test float round up # Test hashing of ints vs floats testHash2 = hashlib.sha1() self.nodeConfig.hashElem(testHash2, testInt1) hash2Value = testHash2.digest() assert(hash1Value != hash2Value) # Test float not truncated def test_protobufConversion(self): """Tests conversion between json and protobuf configuration representations.""" # Convert json data to protobuf format with open (configFilePath, "r") as jsonFile: configData = json.load(jsonFile) #protobuf = self.nodeConfig.toProtoBuf(configData) protobuf = NodeConfig.toProtoBuf(configData) # Convert back to json representation #fromProtobuf = self.nodeConfig.fromProtoBuf(protobuf.SerializeToString()) fromProtobuf = NodeConfig.fromProtoBuf(protobuf.SerializeToString()) # Hash config instance from conversion and compare to initial configuration nc_protobuf = NodeConfig(configData=fromProtobuf) assert(self.nodeConfig.calculateHash() == nc_protobuf.calculateHash()) def checkConfigEntries(self, testEntries, testCondition, configEntries=None): if configEntries == None: configEntries = list(self.nodeConfig.__dict__.keys()) for key in testEntries: # Check if key in configuration print("Testing " + str(key) + " in " + str(configEntries)) assert ((key in configEntries) == testCondition) ## Check for any subkeys #if list(testEntries[i]): # Check if entry is a list of entries # for subkey in testEntries[i]: # print(eval('self.nodeConfig.' + entries[i]), truthEntries[i]) # assert (subkey in eval('self.nodeConfig.' + key) == testCondition) def updateTestNodeConfigData(self, platform): """Update appropriate config data prior to testing.""" configTruthData['platform'] = platform