示例#1
0
    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
示例#2
0
    def __init__(self, configFile=[], config=[]):
        if configFile:
            self.config = NodeConfig(configFile)
        elif config:
            self.config = config

        self.setupParams()
示例#3
0
    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())
示例#4
0
    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]
示例#5
0
    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)
示例#6
0
    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)
示例#7
0
    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)
示例#8
0
    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()
示例#9
0
    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")
示例#10
0
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']
示例#11
0
    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())
示例#12
0
 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
示例#13
0
 def test_missingConfigEntry(self):
     """Test for missing configuration entry in configuration file."""
     with pytest.raises(KeyError) as e:
         nodeConfig = NodeConfig(badConfigFilePath)
     pass  
示例#14
0
 def test_invalidFileLoad(self):
     """Test for failed load due to bad configuration file."""
     with pytest.raises(customExceptions.NodeConfigFileError) as e:
         nodeConfig = NodeConfig("invalidFile")
示例#15
0
 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)
示例#16
0
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
示例#17
0
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