def test_page_call_with_prevent_transaction_loss_ajax(pyramid_req): # first create a default setup: a page with a root node and a valid transaction page = Page(None, pyramid_req) page.root_node = ComponentContainerBase page.handle_transaction() # thats what we want and how it should be assert '__initialized_components__' in page.transaction assert 'root_node' in page.transaction['__initialized_components__'] # a transaction can be lost (for example) by reaching the timeout setting of the transaction store # we simulate this deleting the memory storage and the transaction cache via _data page.request.registry.transaction_memory = {} page.transaction._data = {} # now there are no __initialized_components__ in it any more assert '__initialized_components__' not in page.transaction # setting up a valid ajax request page.request.is_xhr = True page.page_request.params = {"q": []} # now calling the page will force a location.reload() on the browser result = page() assert result.text == 'window.location.reload();'
def test_page_call_with_prevent_transaction_loss_html(pyramid_req): # first create a default setup: a page with a root node and a valid transaction page = Page(None, pyramid_req) page.root_node = ComponentContainerBase page.handle_transaction() original_tid = page.transaction.tid # thats what we want and how it should be assert '__initialized_components__' in page.transaction assert 'root_node' in page.transaction['__initialized_components__'] # a transaction can be lost (for example) by reaching the timeout setting of the transaction store # we simulate this deleting the memory storage and the transaction cache via _data page.request.registry.transaction_memory = {} page.transaction._data = {} # now there are no __initialized_components__ in it any more assert '__initialized_components__' not in page.transaction # calling the page will call prevent_transaction_loss which should add the __initialized_components__ again page() assert '__initialized_components__' in page.transaction assert 'root_node' in page.transaction['__initialized_components__'] # also note: this is not a _new_ transaction object - the tid is the same as before # but the data will be resetted to the initial state assert original_tid == page.transaction.tid
def test_unicode_ajax_response(pyramid_req): """Check if the rendering process generates all a valid utf-8 encoded response """ # Create a Transaction with an assigned root_node. page = Page(None, pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) page.handle_transaction() # Generate a response with a unicode string. page.root_node.add_js_response(u'console.log("ää");') # Redraw and handle_ajax_events, so that all necessary output will be generated. page.root_node.redraw() page.handle_ajax_events() assert True not in [c.is_rendered for c in page.get_active_components()] out = page.render() assert u'console.log("ää");' in out out.encode('utf-8')
def test_unicode_ajax_response(pyramid_req): """Check if the rendering process generates all a valid utf-8 encoded response """ # Create a Transaction with an assigned root_node. page = Page(None, pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) page.handle_transaction() # Generate a response with a unicode string. page.root_node.add_js_response(u'console.log("ää");') # Redraw and handle_ajax_events, so that all necessary output will be generated. page.root_node.redraw() page.handle_ajax_events() assert True not in [c.is_rendered for c in page.get_active_components()] out = page.render() assert u'console.log("ää");' in out out.encode('utf-8')
def test_component_rendering_ajax(pyramid_req): """Check if the rendering process generates all required AJAX scripts. """ # Create a Transaction with an assigned root_node. page = Page(pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) page.handle_transaction() base_components = 10 leaf_components = 200 # Generate a nice round 210 child components. page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) for i in range(0, base_components): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) for x in range(0, leaf_components): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) # Redraw and handle_ajax_events, so that all necessary output will be generated. page.root_node.redraw() page.handle_ajax_events() assert True not in [c.is_rendered for c in page.get_active_components()] # start_time = time.time() out = page.render() # print base_components, leaf_components, int((time.time() - start_time) * 1000000) # Checking set_component_info calls required to tell EPFLs JS what the component is capable of. for i in range(0, base_components): assert ('epfl.set_component_info(\\"child_node_%s\\", \\"handle\\", [\'change\', \'reinitialize\', ' '\'set_row\']);' % (i + 1)) in out, "Missing set component info for child_node_%s" % (i + 1) out = out.replace('epfl.set_component_info("child_node_%s", "handle", [\'set_row\']);' % (i + 1), '') for x in range(0, leaf_components): assert ('epfl.set_component_info(\\"child_node_%s_%s\\", \\"handle\\", [\'change\', \'reinitialize\', ' '\'set_row\']);' % (i + 1, x)) in out out = out.replace('epfl.set_component_info("child_node_%s_%s", "handle", [\'change\', \'set_row\']);' % (i + 1, x), '') assert 'epfl.set_component_info(\\"child_node_0\\", \\"handle\\", [\'change\', \'reinitialize\', \'set_row\']);' \ 'epfl.set_component_info(\\"root_node\\", \\"handle\\", [\'change\', \'reinitialize\', \'set_row\']);' in out
def test_component_deletion_and_recreation(pyramid_req): """Check if anything goes wrong when components are deleted and then created fresh. """ page = Page(None, pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) page.handle_transaction() def create_child_components(): page.root_node.add_component( ComponentContainerBase(cid='child_node_0')) for i in range(0, 10): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) for x in range(0, 3): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) # Create child components... create_child_components() # ... make sure they're available... assert len(page.root_node.components) == 1 # ... delete them... page.child_node_0.delete_component() # ... make sure they've been deleted properly... assert transaction['compo_store'].keys() == ['root_node'] assert transaction.get_component('root_node') == { 'cid': 'root_node', 'compo_struct': [], 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) } assert len(page.root_node.components) == 0 # ... create new child components... create_child_components() # ... make sure they're available... assert len(page.root_node.components) == 1 # ... make sure they're available in transaction as well... assert len(transaction['compo_store']) == 42 # ... make sure a random child node is available as well. Random numbers generated by fair dice roll. assert page.child_node_4_1
def test_component_deletion_and_recreation(pyramid_req): """Check if anything goes wrong when components are deleted and then created fresh. """ page = Page(pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) page.handle_transaction() def create_child_components(): page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) for i in range(0, 10): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) for x in range(0, 3): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) # Create child components... create_child_components() # ... make sure they're available... assert len(page.root_node.components) == 1 # ... delete them... page.child_node_0.delete_component() # ... make sure they've been deleted properly... assert transaction['compo_lookup'] == {} assert transaction.get_component('root_node') == {'cid': 'root_node', 'compo_struct': OrderedDict(), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))} assert len(page.root_node.components) == 0 # ... create new child components... create_child_components() # ... make sure they're available... assert len(page.root_node.components) == 1 # ... make sure they're available in transaction as well... assert len(transaction['compo_lookup']) == 41 # ... make sure a random child node is available as well. Random numbers generated by fair dice roll. assert page.child_node_4_1
def test_js_helper_methods(pyramid_req, function_name, kwargs, snippet_in_response): """ test the functions with their parameters which use add_js_response add result. """ page = Page(None, pyramid_req) page.root_node = ComponentContainerBase page.handle_transaction() func = getattr(page, function_name) func(**kwargs) response = page() assert snippet_in_response in response.text
def test_basic_component_regeneration(pyramid_req): """Test the component regeneration operations of the page api. """ # Create a Transaction with assigned components. page = Page(pyramid_req) page.root_node = ComponentContainerBase t = page.transaction t['components_assigned'] = True t.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('27a3d2ef7f76417bb2ebde9853f0c2a6', None))}) t.set_component('child_node', {'slot': None, 'ccid': 'root_node', 'config': {'test': None, 'compo_state': ['test']}, 'class': (ComponentBase, {'test': None, 'compo_state': ['test']}, ('child_node', None)), 'cid': 'child_node', 'compo_state': {'test': 'foobar'}}) # handle_transaction now has to restore the components from the transaction into their loaded state. page.handle_transaction() assert page.root_node is not None and page.child_node is not None, \ "Components inserted into transaction were not loaded in epfl." assert page.child_node.test == 'foobar', \ "Component attributes inserted into transaction were not loaded in epfl." # Set a value into a child node attribute that should be in the compo_state. page.child_node.test = {'some': 'dict'} assert t.get_component('child_node')['compo_state']['test'] == {'some': 'dict'}, \ "Stored attribute wasn't stored properly in the transaction compo_state." # Generate a new Page instance and regenerate everything from the transaction again. new_page = Page(pyramid_req, transaction=t) new_page.handle_transaction() # If this seems familiar you have payed attention. Congratulations. For everyone else: Read two comments up. assert t.get_component('child_node')['compo_state']['test'] == {'some': 'dict'} assert new_page.child_node.test == {'some': 'dict'}
def test_basic_component_operations(pyramid_req): """Test the basic component operations of the page api. """ page = Page(None, pyramid_req) t = page.transaction # A component set as root_node must appear in the transaction after handle_transaction. page.root_node = ComponentContainerBase page.handle_transaction() assert t.has_component('root_node') # After handle_transaction it must be possible to add child components dynamically to the root_node. page.root_node.add_component( ComponentBase(cid='child_node', compo_state=['test'], test=None)) assert t.has_component('child_node')
def test_basic_component_operations(pyramid_req): """Test the basic component operations of the page api. """ page = Page(pyramid_req) t = page.transaction # A component set as root_node must appear in the transaction after handle_transaction. page.root_node = ComponentContainerBase page.handle_transaction() assert t.has_component('root_node') # After handle_transaction it must be possible to add child components dynamically to the root_node. page.root_node.add_component(ComponentBase(cid='child_node', compo_state=['test'], test=None)) assert t.has_component('child_node')
def test_component_rendering_ajax(pyramid_req): """Check if the rendering process generates all required AJAX scripts. """ # Create a Transaction with an assigned root_node. page = Page(None, pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) page.handle_transaction() base_components = 10 leaf_components = 200 # Generate a nice round 210 child components. page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) for i in range(0, base_components): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) for x in range(0, leaf_components): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) # Redraw and handle_ajax_events, so that all necessary output will be generated. page.root_node.redraw() page.handle_ajax_events() assert True not in [c.is_rendered for c in page.get_active_components()] # start_time = time.time() out = page.render()
def test_component_deletion(pyramid_req): """Check if anything goes wrong when components are deleted. """ page = Page(None, pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) # Instantiate the pre generated component from the transaction. page.handle_transaction() # Add a container for our children doomed to be deleted. page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) # Generate some doomed children. for i in range(0, 10): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) getattr(page, 'child_node_%s' % (i + 1)) for x in range(0, 3): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) getattr(page, 'child_node_%s_%s' % (i + 1, x)) # Chop the children off at their respective root. page.child_node_0.delete_component() # Make sure they're really dead. assert transaction.has_component('child_node_0') is False for i in range(0, 10): assert transaction.has_component('child_node_%s' % (i + 1)) is False for x in range(0, 3): assert transaction.has_component('child_node_%s_%s' % (i + 1, x)) is False
def test_component_rendering_ajax(pyramid_req): """Check if the rendering process generates all required AJAX scripts. """ # Create a Transaction with an assigned root_node. page = Page(None, pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) page.handle_transaction() base_components = 10 leaf_components = 200 # Generate a nice round 210 child components. page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) for i in range(0, base_components): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) for x in range(0, leaf_components): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) # Redraw and handle_ajax_events, so that all necessary output will be generated. page.root_node.redraw() page.handle_ajax_events() assert True not in [c.is_rendered for c in page.get_active_components()] # start_time = time.time() out = page.render()
def test_component_deletion(pyramid_req): """Check if anything goes wrong when components are deleted. """ page = Page(pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) # Instantiate the pre generated component from the transaction. page.handle_transaction() # Add a container for our children doomed to be deleted. page.root_node.add_component(ComponentContainerBase(cid='child_node_0')) # Generate some doomed children. for i in range(0, 10): getattr(page, 'child_node_%s' % i) \ .add_component(ComponentContainerBase(cid='child_node_%s' % (i + 1))) getattr(page, 'child_node_%s' % (i + 1)) for x in range(0, 3): getattr(page, 'child_node_%s' % (i + 1)) \ .add_component(ComponentContainerBase(cid='child_node_%s_%s' % (i + 1, x))) getattr(page, 'child_node_%s_%s' % (i + 1, x)) # Chop the children off at their respective root. page.child_node_0.delete_component() # Make sure they're really dead. assert transaction.has_component('child_node_0') is False for i in range(0, 10): assert transaction.has_component('child_node_%s' % (i + 1)) is False for x in range(0, 3): assert transaction.has_component('child_node_%s_%s' % (i + 1, x)) is False
def test_container_assign(pyramid_req): """Check if components are assigned to the proper containers. """ Page.root_node = ComponentContainerBase( cid='root_node', node_list=[ ComponentContainerBase( cid='container_1', node_list=[ ComponentBase(cid='compo_1') ] ), ComponentContainerBase( cid='container_2', node_list=[ ComponentBase(cid='compo_2') ] ), ComponentContainerBase( cid='container_3', node_list=[ ComponentBase(cid='compo_3') ] ), ComponentContainerBase( cid='container_4', node_list=[ ComponentBase(cid='compo_4') ] ), ] ) page = Page(pyramid_req) page.handle_transaction() # The two trailing chars have to be the same. for compo in page.root_node.components: assert compo.cid[-2:] == compo.compo_info['compo_struct'].keys()[0][-2:]
def test_container_assign(pyramid_req): """Check if components are assigned to the proper containers. """ Page.root_node = ComponentContainerBase( cid='root_node', node_list=[ ComponentContainerBase(cid='container_1', node_list=[ComponentBase(cid='compo_1')]), ComponentContainerBase(cid='container_2', node_list=[ComponentBase(cid='compo_2')]), ComponentContainerBase(cid='container_3', node_list=[ComponentBase(cid='compo_3')]), ComponentContainerBase(cid='container_4', node_list=[ComponentBase(cid='compo_4')]), ]) page = Page(None, pyramid_req) page.handle_transaction() # The two trailing chars have to be the same. for compo in page.root_node.components: assert compo.cid[-2:] == compo.compo_info['compo_struct'][0][-2:]
def test_re_rendering_components(pyramid_req): """Check if components can be rendered correctly when regenerated from a Transaction. """ # Generate a transaction with the appropriate components. page = Page(pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) transaction.set_component('child_node_0', {'ccid': 'root_node', 'cid': 'child_node_0', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_0', None))}) # This one is about precision, 55 components suffice, we're not after performance here. compo_depth = 5 compo_width = 10 for i in range(0, compo_depth): transaction.set_component('child_node_%s' % (i + 1), {'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s' % (i + 1), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s' % (i + 1), None))}) for x in range(0, compo_width): transaction.set_component('child_node_%s_%s' % (i + 1, x), {'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s_%s' % (i + 1, x), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s_%s' % (i + 1, x), None))}) # Set everything up. page.handle_transaction() # root_node redraw should supersede following child redraws. page.root_node.redraw() page.child_node_3_1.redraw() page.handle_ajax_events() out = page.render() # Make sure the appropriate replace_component calls are all there. Almost exclusively JS, since HTML will be in the # root_node replace_component. for i in range(0, compo_depth): assert out.count( "epfl.replace_component('child_node_%s'" % (i + 1) ) == out.count("epfl.replace_component('child_node_0'") for x in range(0, compo_width): assert out.count( "epfl.replace_component('child_node_%s_%s'" % (i + 1, x) ) == out.count("epfl.replace_component('child_node_0'")
def test_re_rendering_components(pyramid_req): """Check if components can be rendered correctly when regenerated from a Transaction. """ # Generate a transaction with the appropriate components. page = Page(None, pyramid_req) page.request.is_xhr = True page.page_request.params = {"q": []} transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) transaction.set_component( 'child_node_0', { 'ccid': 'root_node', 'cid': 'child_node_0', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_0', None)) }) # This one is about precision, 55 components suffice, we're not after performance here. compo_depth = 5 compo_width = 10 for i in range(0, compo_depth): transaction.set_component( 'child_node_%s' % (i + 1), { 'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s' % (i + 1), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s' % (i + 1), None)) }) for x in range(0, compo_width): transaction.set_component( 'child_node_%s_%s' % (i + 1, x), { 'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s_%s' % (i + 1, x), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s_%s' % (i + 1, x), None)) }) # Set everything up. page.handle_transaction() # root_node redraw should supersede following child redraws. page.root_node.redraw() page.child_node_3_1.redraw() page.handle_ajax_events() out = page.render() # Make sure the appropriate replace_component calls are all there. Almost exclusively JS, since HTML will be in the # root_node replace_component. for i in range(0, compo_depth): assert out.count( "epfl.replace_component('child_node_%s'" % (i + 1)) == out.count("epfl.replace_component('child_node_0'") for x in range(0, compo_width): assert out.count( "epfl.replace_component('child_node_%s_%s'" % (i + 1, x)) == out.count("epfl.replace_component('child_node_0'")
def test_component_regeneration_performance(pyramid_req): """Test the speed of the component regeneration operations of the page api. """ # Create a page, then create a transaction with a ton of components. page = Page(None, pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None)) }) transaction.set_component( 'child_node_0', { 'ccid': 'root_node', 'cid': 'child_node_0', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_0', None)) }) # There still is a non linear scaling factor in EPFLs rendering process.The non linear part is strongly depth # dependent so this test reflects what happens in 2 layers with 10.000 child components total. compo_depth = 10 compo_width = 1000 # Store time for beginning, then start adding the components into the transaction. steps = [time.time()] for i in range(0, compo_depth): transaction.set_component( 'child_node_%s' % (i + 1), { 'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s' % (i + 1), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s' % (i + 1), None)) }) for x in range(0, compo_width): transaction.set_component( 'child_node_%s_%s' % (i + 1, x), { 'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s_%s' % (i + 1, x), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s_%s' % (i + 1, x), None)) }) steps.append(time.time()) # Calling this will generate everything. Or rather, will setup everything so it can be generated just in time. This # tends to be quite speedy nowadays, but it used to be a major bottleneck. page.handle_transaction() steps.append(time.time()) output = page.render() steps.append(time.time()) assert (steps[2] - steps[1]) * 1. / compo_depth / compo_width < 1. / 10000, \ 'Component transaction handling exceeded limits. (%r >= %r)' % ( (steps[2] - steps[1]) * 1. / compo_depth / compo_width, 1. / 10000) # 0.0001s per component are OK. assert (steps[3] - steps[2]) * 1. / compo_depth / compo_width < 1. / 100, \ 'Component transaction handling exceeded limits. (%r >= %r)' % ( (steps[3] - steps[2]) * 1. / compo_depth / compo_width, 1. / 100) # .01s for rendering a component are ok.
def test_component_regeneration_performance(pyramid_req): """Test the speed of the component regeneration operations of the page api. """ # Create a page, then create a transaction with a ton of components. page = Page(pyramid_req) transaction = page.transaction transaction['components_assigned'] = True transaction.set_component('root_node', {'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('root_node', None))}) transaction.set_component('child_node_0', {'ccid': 'root_node', 'cid': 'child_node_0', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_0', None))}) # There still is a non linear scaling factor in EPFLs rendering process.The non linear part is strongly depth # dependent so this test reflects what happens in 2 layers with 10.000 child components total. compo_depth = 10 compo_width = 1000 # Store time for beginning, then start adding the components into the transaction. steps = [time.time()] for i in range(0, compo_depth): transaction.set_component('child_node_%s' % (i + 1), {'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s' % (i + 1), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s' % (i + 1), None))}) for x in range(0, compo_width): transaction.set_component('child_node_%s_%s' % (i + 1, x), {'ccid': 'child_node_%s' % i, 'cid': 'child_node_%s_%s' % (i + 1, x), 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('child_node_%s_%s' % (i + 1, x), None))}) steps.append(time.time()) # Calling this will generate everything. Or rather, will setup everything so it can be generated just in time. This # tends to be quite speedy nowadays, but it used to be a major bottleneck. page.handle_transaction() steps.append(time.time()) output = page.render() steps.append(time.time()) assert (steps[2] - steps[1]) * 1. / compo_depth / compo_width < 1. / 10000, \ 'Component transaction handling exceeded limits. (%r >= %r)' % ( (steps[2] - steps[1]) * 1. / compo_depth / compo_width, 1. / 10000) # 0.0001s per component are OK. assert (steps[3] - steps[2]) * 1. / compo_depth / compo_width < 1. / 100, \ 'Component transaction handling exceeded limits. (%r >= %r)' % ( (steps[3] - steps[2]) * 1. / compo_depth / compo_width, 1. / 100) # .01s for rendering a component are ok.
def test_basic_component_regeneration(pyramid_req): """Test the component regeneration operations of the page api. """ # Create a Transaction with assigned components. page = Page(None, pyramid_req) page.root_node = ComponentContainerBase t = page.transaction t['components_assigned'] = True t.set_component( 'root_node', { 'cid': 'root_node', 'slot': None, 'config': {}, 'class': (ComponentContainerBase, {}, ('27a3d2ef7f76417bb2ebde9853f0c2a6', None)) }) t.set_component( 'child_node', { 'slot': None, 'ccid': 'root_node', 'config': { 'test': None, 'compo_state': ['test'] }, 'class': (ComponentBase, { 'test': None, 'compo_state': ['test'] }, ('child_node', None)), 'cid': 'child_node', 'compo_state': { 'test': 'foobar' } }) # handle_transaction now has to restore the components from the transaction into their loaded state. page.handle_transaction() assert page.root_node is not None and page.child_node is not None, \ "Components inserted into transaction were not loaded in epfl." assert page.child_node.test == 'foobar', \ "Component attributes inserted into transaction were not loaded in epfl." # Set a value into a child node attribute that should be in the compo_state. page.child_node.test = {'some': 'dict'} assert t.get_component('child_node')['compo_state']['test'] == {'some': 'dict'}, \ "Stored attribute wasn't stored properly in the transaction compo_state." # Generate a new Page instance and regenerate everything from the transaction again. new_page = Page(None, pyramid_req, transaction=t) new_page.handle_transaction() # If this seems familiar you have payed attention. Congratulations. For everyone else: Read two comments up. assert t.get_component('child_node')['compo_state']['test'] == { 'some': 'dict' } assert new_page.child_node.test == {'some': 'dict'}