seems nearly all the message template building code is tested and covered (would be 100% if the testrunner didn't include import statements and class method definitions)

This commit is contained in:
locklainn.linden
2008-07-24 19:52:35 +00:00
committed by Salad Dais
parent 03f309b012
commit 6857444a27
3 changed files with 209 additions and 55 deletions

View File

@@ -77,8 +77,8 @@ class MsgBlockData(object):
def add_variable(self, var):
self.variable_map[var.name] = var
def add_data(self, var_name, data, data_size):
self.get_variable(var_name).add_data(data, data_size)
def add_data(self, var_name, data, size):
self.get_variable(var_name).add_data(data, size)
class MsgVariableData(object):
""" Used as a Message Block variable that is being created that will be
@@ -87,15 +87,14 @@ class MsgVariableData(object):
self.name = name
#data_size holds info whether or not the variable is of type
#MVT_VARIABLE
self.data_size = 0
self.size = -1
self.type = tp
self.data = None
#how DO we add data? What format will it be in?
def add_data(self, data, data_size):
def add_data(self, data, size):
self.data = data
self.size = data_size
self.size = size
class MessageTemplateVariable(object):
def __init__(self, name, tp, size):
@@ -105,6 +104,7 @@ class MessageTemplateVariable(object):
class MessageTemplateBlock(object):
def __init__(self, name):
self.variables = []
self.variable_map = {}
self.name = name
self.block_type = None
@@ -112,15 +112,17 @@ class MessageTemplateBlock(object):
def add_variable(self, var):
self.variable_map[var.name] = var
self.variables.append(var)
def get_variables(self):
return self.variable_map.values()
return self.variables #self.variable_map.values()
def get_variable(self, name):
return self.variable_map[name]
class MessageTemplate(object):
def __init__(self, name):
self.blocks = []
self.block_map = {}
#this is the function or object that will handle this type of message
self.handler = None
@@ -138,9 +140,10 @@ class MessageTemplate(object):
def add_block(self, block):
self.block_map[block.name] = block
self.blocks.append(block)
def get_blocks(self):
return self.block_map.values()
return self.blocks #self.block_map.values()
def get_block(self, name):
return self.block_map[name]

View File

@@ -24,12 +24,6 @@ class MessageTemplateBuilder(object):
self.cur_block_name = ''
self.packer = DataPacker()
def get_current_message(self):
return self.current_msg
def get_current_block(self):
return self.current_block
def build_message(self):
""" Builds the message by serializing the data. Creates a packet ready
@@ -90,18 +84,19 @@ class MessageTemplateBuilder(object):
bytes += 1
for block in block_list:
for variable in message_block.get_variables():
for v in template_block.get_variables(): #message_block.get_variables():
#this mapping has to occur to make sure the data is written in correct order
variable = message_block.get_variable(v.name)
var_size = variable.size
if var_size == -1:
raise Exception('Variable ' + variable.name + ' in block ' + \
message_block.name + ' of message ' + message_data.name + \
' wasn"t set prior to buildMessage call')
data_size = variable.data_size
#variable's data_size represents whether or not it is of the type
#MVT_VARIABLE. If it is positive, it is
if data_size > 0:
#if its a VARIABLE type, we have to write in the size of the data
if variable.type == MsgType.MVT_VARIABLE:
data_size = template_block.get_variable(variable.name).size
if data_size == 1:
block_buffer += struct.pack('>B', var_size)
elif data_size == 2:
@@ -136,11 +131,8 @@ class MessageTemplateBuilder(object):
self.current_msg.add_block(block_data)
def next_block(self, block_name):
#if it doesn't exist, create a new block (may be a VARIABLE or MULTIPLE type
#block
if block_name not in self.current_template.block_map:
#error:
print 'ERROR: template doesn"t have the block'
return
template_block = self.current_template.get_block(block_name)
@@ -159,40 +151,64 @@ class MessageTemplateBuilder(object):
return
#although we may have a block already, there are some cases where we can have
#more than one block of the same name (when type is MULTIPLE or VARIABLE)
#more than one block of the same name (when type is MULTIPLE or VARIABLE), so we
#might have to create a whole new block
else:
#make sure it isn't SINGLE
if self.template_block.type == MsgBlockType.MBT_SINGLE:
#error: can't have more than 1 block when its supposed to be 1
print 'ERROR: can"t have more than 1 block when its supposed to be 1'
return
#make sure it isn't SINGLE and trying to create a new block
if template_block.type == MsgBlockType.MBT_SINGLE:
raise Exception('ERROR: can"t have more than 1 block when its supposed to be 1')
elif self.template_block.type == MsgBlockType.MBT_MULTIPLE and \
self.template_block.block_number == block_data.block_number:
#error: we are about to exceed block total
print 'ERROR: we are about to exceed block total'
return
elif template_block.type == MsgBlockType.MBT_MULTIPLE and \
template_block.block_number == block_data.block_number:
raise Exception('ERROR: we are about to exceed block total')
block_data.block_number += 1
self.current_block = MsgBlockData(block.name)
self.current_block = MsgBlockData(block_name)
self.current_msg.add_block(self.current_block)
self.cur_block_name = block_name
for variable in self.current_block.variables:
for variable in template_block.get_variables():
var_data = MsgVariableData(variable.name, variable.type)
self.current_block.add_variable(var_data)
def add_data(self, var_name, data, data_type):
""" the data type is passed in to make sure that the programmer is aware of
what type (and therefore size) of the data that is being passed in. """
self.__check_size(var_name, data, data_type)
self.current_block.add_data(var_name, data, data_type)
if self.current_template == None:
raise Exception('Attempting to add data to a null message')
def __check_size(self, var_name, data, data_type):
if self.current_block == None:
raise Exception('Attempting to add data to a null block')
template_variable = self.current_template.get_block(self.cur_block_name).get_variable(var_name)
if template_variable == None:
raise Exception('Variable is not in the block')
#this should be the size of the actual data
size = sizeof(data_type)
if data_type == MsgType.MVT_VARIABLE:
#if its a MVT_VARIABLE type of data, then size will be -1 for the type
#so the actual size we will have to get from the data itself
#HACK - this may cause a bug if the data type doesn't have len
size = len(data)
#template holds the max size the data can be
data_size = template_variable.size
#error check - size can't be larger than the bytes will hold
self.current_block.add_data(var_name, data, size)
else:
#size check can't be done on VARIABLE sized variables
if self.__check_size(var_name, data, size) == False:
raise Exception('Variable size isn"t the same as the template size')
self.current_block.add_data(var_name, data, size)
def __check_size(self, var_name, data, data_size):
block = self.template_list[self.cur_msg_name].get_block(self.cur_block_name)
data_size = sizeof(data_type)
size = block.get_variable(var_name).size
if size != data_size:
#warning
#for now, exception
raise Exception('Variable size isn"t the same as the template size')
return False
return True

View File

@@ -1,5 +1,6 @@
#standard libraries
import unittest, doctest
from uuid import UUID
#local libraries
from pyogp.lib.base.data import msg_tmpl
@@ -8,7 +9,7 @@ from pyogp.lib.base.message_template_parser import MessageTemplateParser
from pyogp.lib.base.message_template_builder import MessageTemplateBuilder
from pyogp.lib.base.message_template_dict import TemplateDictionary
from pyogp.lib.base.message_types import MsgType
from indra.base.lluuid import UUID
#from indra.base.lluuid import UUID
class TestTemplateBuilder(unittest.TestCase):
@@ -36,18 +37,18 @@ class TestTemplateBuilder(unittest.TestCase):
except:
assert True
assert builder.get_current_message() == None, "Created a message despite its non-existence"
assert builder.current_msg == None, "Created a message despite its non-existence"
def test_create_message(self):
builder = MessageTemplateBuilder(self.template_dict)
assert builder.get_current_message() == None, "Message exists before it was created"
assert builder.current_msg == None, "Message exists before it was created"
builder.new_message('AddCircuitCode')
assert builder.get_current_message() != None, "Create message failed"
assert builder.current_msg != None, "Create message failed"
def test_create_message_blocks(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('AvatarTextureUpdate')
blocks = builder.get_current_message().block_map
blocks = builder.current_msg.block_map
assert len(blocks) == 3, "Blocks not added to the message"
try:
t_block = blocks['AgentData']
@@ -70,10 +71,10 @@ class TestTemplateBuilder(unittest.TestCase):
def test_next_block(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('AvatarTextureUpdate')
assert builder.get_current_block() == None, "Message block exists before it was created"
assert builder.current_block == None, "Message block exists before it was created"
builder.next_block('AgentData')
assert builder.get_current_block() != None, "Setting next block failed"
assert builder.get_current_block().name == 'AgentData', "Wrong block set"
assert builder.current_block != None, "Setting next block failed"
assert builder.current_block.name == 'AgentData', "Wrong block set"
def test_next_block_fail(self):
builder = MessageTemplateBuilder(self.template_dict)
@@ -84,13 +85,88 @@ class TestTemplateBuilder(unittest.TestCase):
assert False, "Using block AgentSocialIdeas that doesn't exist"
except:
assert True
assert builder.get_current_block() == None, "Set block without one existing"
assert builder.current_block == None, "Set block without one existing"
def test_next_single(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('TestMessage')
builder.next_block('TestBlock1')
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
try:
builder.next_block('TestBlock1')
assert False, "Adding 2 blocks of the same type to a MBT_SINGLE block"
except:
assert True
def test_nextmultiple_exceed(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('TestMessage')
builder.next_block('TestBlock1')
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
try:
builder.next_block('NeighborBlock')
assert False, "Allowed to add more than specified number of blocks"
except:
assert True
def test_build_variable(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('PacketAck')
builder.next_block('Packets')
builder.add_data('ID', 0x00000001, MsgType.MVT_U32)
builder.next_block('Packets')
builder.add_data('ID', 0x00000001, MsgType.MVT_U32)
msg, size = builder.build_message()
assert msg == '\xff\xff\xff\xfb' + '\x02' + \
'\x00\x00\x00\x01\x00\x00\x00\x01', \
"Building variable block failed"
def test_build_empty_var(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('PacketAck')
builder.next_block('Packets')
try:
msg, size = builder.build_message()
assert False, "Building with a variable that wasn't set"
except:
assert True
def test_build_variable_var(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('UpdateSimulator')
builder.next_block('SimulatorInfo')
builder.add_data('RegionID', UUID("550e8400-e29b-41d4-a716-446655440000"), MsgType.MVT_LLUUID)
builder.add_data('SimName', "Testing", MsgType.MVT_VARIABLE)
builder.add_data('EstateID', 0x00000001, MsgType.MVT_U32)
builder.add_data('SimAccess', 0x01, MsgType.MVT_U8)
msg, size = builder.build_message()
assert_string = '\xff\xff\x00\x11' + UUID("550e8400-e29b-41d4-a716-446655440000").bytes + \
'\x07' + 'Testing' + '\x00\x00\x00\x01' + '\x01'
assert msg == assert_string, "Building variable block failed"
def test_next_block_variables(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('AvatarTextureUpdate')
builder.next_block('AgentData')
variables = builder.get_current_block().variable_map
variables = builder.current_block.variable_map
assert len(variables) == 2, "Variables not added to the block"
try:
@@ -115,7 +191,7 @@ class TestTemplateBuilder(unittest.TestCase):
builder.next_block('AgentData')
builder.add_data('TexturesChanged', True, MsgType.MVT_BOOL)
#need a way to determine the right variable data is sent compared to the type
assert builder.get_current_block().variable_map['TexturesChanged'].data == True,\
assert builder.current_block.variable_map['TexturesChanged'].data == True,\
"Data not set correctly"
def test_add_lluuid(self):
@@ -123,9 +199,9 @@ class TestTemplateBuilder(unittest.TestCase):
builder.new_message('AvatarTextureUpdate')
builder.next_block('AgentData')
builder.add_data('AgentID', UUID("550e8400-e29b-41d4-a716-446655440000"), MsgType.MVT_LLUUID)
assert builder.get_current_block().variable_map['AgentID'].data == UUID("550e8400-e29b-41d4-a716-446655440000"),\
assert builder.current_block.variable_map['AgentID'].data == UUID("550e8400-e29b-41d4-a716-446655440000"),\
"Data not set correctly"
#assert builder.get_current_block().variables['AgentID'].get_size() == ?
#assert builder.current_block.variables['AgentID'].get_size() == ?
#test should go with the packer mostly
def test_serialize_u8_fail(self):
@@ -139,6 +215,65 @@ class TestTemplateBuilder(unittest.TestCase):
except:
assert True
def test_build_fail(self):
builder = MessageTemplateBuilder(self.template_dict)
msg = builder.build_message()
assert msg == None, "Got a message without calling new first"
def test_build_multiple_fail(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('TestMessage')
builder.next_block('TestBlock1')
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
try:
msg, size = builder.build_message()
assert False, "Message block should be 1, where it should be 4"
except:
assert True
def test_build_multiple(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('TestMessage')
builder.next_block('TestBlock1')
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
builder.next_block('NeighborBlock')
builder.add_data('Test0', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test1', 0x00000001, MsgType.MVT_U32)
builder.add_data('Test2', 0x00000001, MsgType.MVT_U32)
msg = None
size = 0
try:
msg, size = builder.build_message()
except Exception, e:
assert False, "Multiple blocks not working correctly"
assert msg == '\xff\xff\x00\x01' + '\x00\x00\x00\x01' + \
'\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01' + \
'\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01' + \
'\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01' + \
'\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01', \
'TestMessage data not built correctly'
def test_serialize_u8(self):
builder = MessageTemplateBuilder(self.template_dict)
builder.new_message('CompletePingCheck')