def test_handle_nack_on_rewritten_computation_further_rewrite(self): """Test if a Nack message is handled correctly for a rewritten computation, when there is a further rewrite""" self.nfn_layer.fib.add_fib_entry(Name('/test'), 1, True) self.nfn_layer.fib.add_fib_entry(Name('/data'), 1, True) computation_name = Name("/func/f1") computation_name += "_(/test/data,/data/test)" computation_name += "NFN" computation_interest = Interest(computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) computation_entry.interest = computation_interest self.nfn_layer.computation_table.append_computation(computation_entry) nack_name = Name("/test/data") nack_name += "/func/f1(_,/data/test)" nack_name += "NFN" self.nfn_layer.forwarding_descision(computation_interest) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], Interest(nack_name)) self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).comp_state, NFNComputationState.REWRITE) self.assertEqual( len( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list), 2) self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list, [ "/func/f1(%/test/data%,/data/test)", "/func/f1(/test/data,%/data/test%)" ]) self.nfn_layer.handleNack( res[1], Nack(nack_name, NackReason.COMP_PARAM_UNAVAILABLE, interest=Interest(nack_name))) second_request_name = Name("/data/test") second_request_name += "/func/f1(/test/data,_)" second_request_name += "NFN" res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], Interest(second_request_name)) self.assertEqual(self.nfn_layer.computation_table.get_container_size(), 1) self.assertEqual( len( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list), 1) self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list, ["/func/f1(/test/data,%/data/test%)"])
def test_handle_nack_on_await_data(self): """Test handle nack on the name of awaiting data""" computation_name = Name("/func/f1") computation_name += "_(/test/data,/data/test)" computation_name += "NFN" computation_interest = Interest(computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) computation_entry.interest = computation_interest self.nfn_layer.computation_table.append_computation(computation_entry) self.assertEqual(self.nfn_layer.computation_table.get_container_size(), 1) self.nfn_layer.computation_table.add_awaiting_data( computation_name, Name("/test/data")) self.assertEqual( len( self.nfn_layer.computation_table.get_computation( computation_name).awaiting_data), 1) self.nfn_layer.handleNack( 1, Nack(Name("/test/data"), NackReason.NO_CONTENT, interest=Interest(Name("/test/data")))) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual( res[1], Nack(computation_name, NackReason.NO_CONTENT, interest=computation_interest)) self.assertEqual(self.nfn_layer.computation_table.get_container(), [])
def test_forward_descision_compute_inner_call(self): """Test if the forward or compute local: goal: compute local with inner call""" self.nfn_layer.fib.add_fib_entry(Name('/test'), 1, True) c1 = Content("/func/f1", "PYTHON\nf\ndef f(a):\n return a.upper()") self.nfn_layer.cs.add_content_object(c1) computation_name = Name("/func/f1") computation_name += "_(/func/f2(/test/data))" computation_name += "NFN" computation_interest = Interest(computation_name) inner_computation_name = Name("/test/data") inner_computation_name += "/func/f2(_)" inner_computation_name += "NFN" inner_computation_interest = Interest(inner_computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) self.nfn_layer.computation_table.append_computation(computation_entry) self.nfn_layer.forwarding_descision(computation_interest) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], Interest(Name("/func/f1"))) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], inner_computation_interest) self.assertTrue(self.nfn_layer.queue_to_lower.empty())
def test_handle_interest(self): """Test if handle interest handles an interest message correctly""" self.nfn_layer.fib.add_fib_entry(Name('/test'), 1, True) c1 = Content("/func/f1", "PYTHON\nf\ndef f(a):\n return a.upper()") self.nfn_layer.cs.add_content_object(c1) computation_name = Name("/func/f1") computation_name += "_(/func/f2(/test/data))" computation_name += "NFN" computation_interest = Interest(computation_name) inner_computation_name = Name("/test/data") inner_computation_name += "/func/f2(_)" inner_computation_name += "NFN" inner_computation_interest = Interest(inner_computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) #self.nfn_layer.computation_table.append_computation(computation_entry) #TODO what does this line? reactive? self.nfn_layer.handleInterest(0, computation_interest) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], Interest(Name("/func/f1"))) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) self.assertEqual(res[1], inner_computation_interest) self.assertTrue(self.nfn_layer.queue_to_lower.empty())
def test_forward_descision_fwd_not_prepended_local(self): """Test if the forward or compute local: forward with not prepended data local available""" self.nfn_layer.fib.add_fib_entry(Name('/test'), 1, True) c1 = Content("/test/data", "Hello World") self.nfn_layer.cs.add_content_object(c1) computation_name = Name("/func/f1") computation_name += "_(1,/test/data)" computation_name += "NFN" computation_interest = Interest(computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) self.nfn_layer.computation_table.append_computation(computation_entry) self.nfn_layer.forwarding_descision(computation_interest) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) compare_name = Name("/test/data") compare_name += "/func/f1(1,_)" compare_name += "NFN" self.assertEqual(res[1], Interest(compare_name)) self.assertEqual( len( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list), 1) self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list[0], "/func/f1(1,%/test/data%)")
def test_forwarding_descision_rewrite(self): """Test if forward or compute local: goal: forward with rewrite""" self.nfn_layer.fib.add_fib_entry(Name('/test'), [1], True) computation_name = Name("/func/f1") computation_name += "_(1,/test/data)" computation_name += "NFN" computation_interest = Interest(computation_name) computation_entry = NFNComputationTableEntry(computation_name) computation_str, prepended = self.nfn_layer.parser.network_name_to_nfn_str( computation_name) computation_entry.ast = self.nfn_layer.parser.parse(computation_str) self.nfn_layer.computation_table.append_computation(computation_entry) self.nfn_layer.forwarding_descision(computation_interest) res = self.nfn_layer.queue_to_lower.get(timeout=2.0) compare_name = Name("/test/data") compare_name += "/func/f1(1,_)" compare_name += "NFN" self.assertEqual(res[1], Interest(compare_name)) self.assertEqual( len( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list), 2) self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list[-1], 'local') self.assertEqual( self.nfn_layer.computation_table.get_computation( computation_name).rewrite_list[0], "/func/f1(1,%/test/data%)")
def fetch_data(self, name: Name, timeout: float = 4.0, use_session: bool = True) -> Optional[str]: """Fetch data from the server :param name Name to be fetched :param timeout Timeout to wait for a response. Use 0 for infinity :param use_session Set to False if sessions shouldn't be used even if they are available. """ if name in self._running_sessions and use_session: # Create interest with session interest: Interest = Interest(self._running_sessions.get(name)) else: # Create normal interest interest: Interest = Interest(name) self._mutex.acquire(blocking=True) self.send_interest(interest) packet = self.receive_packet(timeout) self._mutex.release() if self._session_initiator in interest.name.to_string( ): # Check if we need to handle session initiation new_name = Name(name.components[:-1]) self._pending_sessions.append(new_name) self.handle_session(new_name, packet) if isinstance(packet, Content): self._logger.debug( f"--> One time receive got content: {packet.content}") return packet.content elif isinstance(packet, Nack): self._logger.debug( f"--> One time receive got nack: {packet.reason}") return f"Received Nack: {str(packet.reason.value)}" return None
def test_multiple_calls_params(self): """Test, if ToDataFirstOptimizer works correctly with multiple function calls with parameter""" cmp_name1 = Name("/test/data") cmp_name1 = cmp_name1 + "/func/f1(_,/lib/f2(2,/data/test))" cmp_name1 = cmp_name1 + "NFN" cmp_name2 = Name("/lib/f2") cmp_name2 = cmp_name2 + "/func/f1(/test/data,_(2,/data/test))" cmp_name2 = cmp_name2 + "NFN" workflow = "/func/f1(/test/data,/lib/f2(2,/data/test))" fib = self.optimizer.fib fib.add_fib_entry(Name("/lib"), [1], False) fib.add_fib_entry(Name("/test"), [2], False) self.optimizer.fib = fib ast = self.parser.parse(workflow) self.assertTrue(self.optimizer.compute_fwd(None, ast, Interest(cmp_name1))) self.assertFalse(self.optimizer.compute_local(None, ast, Interest(cmp_name1))) rules = self.optimizer.rewrite(None, ast) self.assertEqual(rules, ['/func/f1(%/test/data%,/lib/f2(2,/data/test))', '/func/f1(/test/data,%/lib/f2%(2,/data/test))', 'local']) name1 = self.parser.nfn_str_to_network_name(rules[0]) self.assertEqual(name1.to_string(), cmp_name1.to_string()) name_str1, prepended1 = self.parser.network_name_to_nfn_str(name1) self.assertEqual(name_str1, workflow) self.assertEqual(prepended1, Name("/test/data")) name2 = self.parser.nfn_str_to_network_name(rules[1]) self.assertEqual(name2, cmp_name2) name_str2, prepended2 = self.parser.network_name_to_nfn_str(name2) self.assertEqual(name_str2, workflow) self.assertEqual(prepended2, Name("/lib/f2"))
def get_next_multiple_names(self, arg: str): """ get next for the multiple name case. Before returning the result the next name get already put into the queue_to_lower. The first name is the only one which is put into the queue immediately before requesting. :param arg: list of the names "sdo:\n\name1\name2\n...\nameN """ self.initialize_get_next_multiple(arg) if self.pos_name_list_multiple < len(self.name_list_multiple) - 1: current_name = self.name_list_multiple[self.pos_name_list_multiple] # Only first call puts two names (current_name and next_name) in the queue_to_lower. Next call only puts next_name if self.pos_name_list_multiple == 0: self.sent_interests[str(current_name)] = True self.queue_to_lower.put( (self.packetid, Interest(current_name))) self.pos_name_list_multiple += 1 next_name = self.name_list_multiple[self.pos_name_list_multiple] if self.check_end_streaming(next_name) is False: self.sent_interests[str(next_name)] = True self.queue_to_lower.put((self.packetid, Interest(next_name))) result = self.get_content(current_name) return result elif self.pos_name_list_multiple == len(self.name_list_multiple) - 1: self.name_list_multiple = None else: return None
def test_keep_alive_ageing_no_reply(self): """test ageing with keepalive with no keep alive reply""" self.timeoutPreventionLayer.ageing() interest = Interest("/test/func/_()/NFN") keepalive = Interest("/test/func/_()/KEEPALIVE/NFN") self.timeoutPreventionLayer.queue_from_higher.put([1, interest]) res1 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res1, [1, interest]) e1 = self.timeoutPreventionLayer.message_dict.get_entry(interest.name) self.assertTrue(e1 is not None) e2 = self.timeoutPreventionLayer.message_dict.get_entry(keepalive.name) self.assertTrue(e2 is not None) res2 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res2, [1, interest]) res3 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res3, [1, keepalive]) res4 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res4, [1, interest]) res5 = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res5, [1, keepalive]) self.assertTrue(self.timeoutPreventionLayer.queue_to_lower.empty()) res7 = self.timeoutPreventionLayer.queue_to_higher.get(timeout=2.0) self.assertEqual(res7, [1, Nack(name=interest.name, reason=NackReason.COMP_NOT_RUNNING, interest=interest)])
def test_register_service(self): """Test service registration and subsequent retrieval of the service list""" self.autoconflayer.start_process() # Send service registration rname = Name('/autoconfig/service') rname += 'udp4://127.42.42.42:1337' rname += 'test' rname += 'repos' rname += 'testrepo' rinterest = Interest(rname) self.faceidtable.add(42, AddressInfo(('127.13.37.42', 4567), 0)) self.queue_from_lower.put([42, rinterest]) # Receive service registration ACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(rname, packet.name) # Request known services list lname = Name('/autoconfig/services') linterest = Interest(lname) self.queue_from_lower.put([42, linterest]) # Receive known services list fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(lname, packet.name) lines: List[str] = [line for line in packet.content.split('\n') if len(line) > 0] self.assertIn('/test/repos/testrepo', lines)
def test_solicitation_no_reply_resend(self): """Test whether a forwarder solicitation is resent if no reply is received""" waittime = self.autoconflayer._solicitation_timeout * 4.0 self.autoconflayer.start_process() interest = Interest(Name('/foo/bar')) self.queue_from_higher.put([None, interest]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the broadcast face was actually created and get its face id bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) # Make sure the forwarder solicitation was sent more than once solictiation = Interest(Name('/autoconfig/forwarders')) solictiation_count = len( [1 for data in tolower if data == [bcfid, solictiation]]) self.assertGreater(solictiation_count, 1)
def test_simple_call_params_to_function_local_prepended_data(self): """Test, if ToDataFirstOptimizer works correctly with a single function call with parameter, to function, compute local since prepended data are local""" cmp_name = Name("/func/f1") cmp_name += "_(/test/data)" cmp_name += "NFN" workflow = "/func/f1(/test/data)" fib = self.optimizer.fib fib.add_fib_entry(Name("/func"), [1], False) self.optimizer.fib = fib prefix = Name("/func/f1") cs = self.optimizer.cs cs.add_content_object( Content(Name("/func/f1"), "PYTHON\nf\ndef f():\n return 'Hello World'"), True) self.optimizer.cs = cs ast = self.parser.parse(workflow) self.assertFalse( self.optimizer.compute_fwd(prefix, ast, Interest(cmp_name))) self.assertTrue( self.optimizer.compute_local(prefix, ast, Interest(cmp_name))) rules = self.optimizer.rewrite(prefix, ast) self.assertEqual(rules, ['%/func/f1%(/test/data)', 'local']) name = self.parser.nfn_str_to_network_name(rules[0]) self.assertEqual(name, cmp_name) name_str, prepended = self.parser.network_name_to_nfn_str(name) self.assertEqual(name_str, workflow) self.assertEqual(prepended, Name("/func/f1"))
def test_register_service_twice_different_addr_nack(self): """Test registration of a second service with a different address under the same name; should be refused""" self.autoconflayer.start_process() # Send first service registration rname = Name('/autoconfig/service') rname += 'udp4://127.42.42.42:1337' rname += 'test' rname += 'repos' rname += 'testrepo' rinterest = Interest(rname) self.faceidtable.add(42, AddressInfo(('127.13.37.42', 4567), 0)) self.queue_from_lower.put([42, rinterest]) # Receive first service registration reply, should be ACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Content) self.assertEqual(rname, packet.name) # Send second service registration with different address fname = Name('/autoconfig/service') fname += 'udp4://127.0.0.42:1337' fname += 'test' fname += 'repos' fname += 'testrepo' finterest = Interest(fname) self.queue_from_lower.put([42, finterest]) # Receive second service registration reply, should be NACK fid, packet = self.queue_to_lower.get() self.assertEqual(42, fid) self.assertIsInstance(packet, Nack) self.assertEqual(NackReason.DUPLICATE, packet.reason) self.assertEqual(fname, packet.name)
def test_simple_call_params(self): """Test, if ToDataFirstOptimizer works correctly with a single function call with parameter""" cmp_name1 = Name("/test/data") cmp_name1 += "/func/f1(_)" cmp_name1 += "NFN" cmp_name2 = Name("/func/f1") cmp_name2 += "_(/test/data)" cmp_name2 += "NFN" workflow = "/func/f1(/test/data)" fib = self.optimizer.fib fib.add_fib_entry(Name("/test"), [1], False) fib.add_fib_entry(Name("/func"), [2], False) self.optimizer.fib = fib ast = self.parser.parse(workflow) self.assertTrue( self.optimizer.compute_fwd(None, ast, Interest(cmp_name1))) self.assertFalse( self.optimizer.compute_local(None, ast, Interest(cmp_name1))) rules = self.optimizer.rewrite(None, ast) self.assertEqual( rules, ['/func/f1(%/test/data%)', '%/func/f1%(/test/data)', 'local']) name1 = self.parser.nfn_str_to_network_name(rules[0]) self.assertEqual(name1, cmp_name1) name_str1, prepended1 = self.parser.network_name_to_nfn_str(name1) self.assertEqual(name_str1, workflow) self.assertEqual(prepended1, Name("/test/data")) name2 = self.parser.nfn_str_to_network_name(rules[1]) self.assertEqual(name2, cmp_name2) name_str2, prepended2 = self.parser.network_name_to_nfn_str(name2) self.assertEqual(name_str2, workflow) self.assertEqual(prepended2, Name("/func/f1"))
def test_split_control_flow(self): """test if the map reduce optimizer splits the control flow correctly""" fib_name1 = Name("/func/f2") fib_name2 = Name("/func/f3") fib = self.optimizer.fib fib.add_fib_entry(fib_name1, [1]) fib.add_fib_entry(fib_name2, [2]) self.optimizer.fib = fib comp = Name("/data/d1") comp += "/func/f1(/func/f2(_),/func/f3(/data/d2))" comp += "NFN" workflow = "/func/f1(/func/f2(/data/d1),/func/f3(/data/d2))" ast = self.parser.parse(str(workflow)) self.assertNotEqual(ast, None) self.assertTrue(self.optimizer.compute_local(None, ast, Interest(comp))) self.assertFalse(self.optimizer.compute_fwd(None, ast, Interest(comp))) self.assertFalse( self.optimizer.compute_local(None, ast.params[0], None)) self.assertTrue(self.optimizer.compute_fwd(None, ast.params[0], None)) self.assertFalse( self.optimizer.compute_local(None, ast.params[1], None)) self.assertTrue(self.optimizer.compute_fwd(None, ast.params[1], None))
def test_solicitation_max_retry(self): """Test that solicitations are not retried ad infinitum and a Nack NO_ROUTE is sent upwards after the timeout""" self.autoconflayer._solicitation_max_retry = 6 waittime = self.autoconflayer._solicitation_timeout * 10 self.autoconflayer.start_process() interest = Interest(Name('/foo/bar')) self.queue_from_higher.put([None, interest]) deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass try: tohigher = self.queue_to_higher.get(timeout=waittime / 10) except queue.Empty: self.fail() bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) solictiation = Interest(Name('/autoconfig/forwarders')) solictiation_count = len( [1 for data in tolower if data == [bcfid, solictiation]]) self.assertEqual(6, solictiation_count) self.assertIsNone(tohigher[0]) self.assertIsInstance(tohigher[1], Nack) self.assertEqual('/foo/bar', tohigher[1].name.components_to_string()) self.assertEqual(NackReason.NO_ROUTE, tohigher[1].reason)
def test_simple_thunk_request_from_lower_data_local_repo(self): """test receiving a thunk request from the network with some data local data in a repo""" self.thunklayer.fib.add_fib_entry(Name("/fct"), [1]) name = Name("/fct/f1") name += "_(/dat/data/d2)" name += "THUNK" name += "NFN" interest = Interest(name) self.thunklayer.queue_from_lower.put([1,interest]) res1 = self.thunklayer.queue_to_lower.get(timeout=2) res2 = self.thunklayer.queue_to_lower.get(timeout=2) self.assertEqual(res1, [1, Interest("/fct/f1/THUNK")]) n1 = Name("/fct/f1") n1 += '_(/dat/data/d2)' n1 += 'THUNK' n1 += 'NFN' self.assertEqual(res2, [1, Interest(n1)]) content1 = Content(res1[1].name, str(4)) self.thunklayer.queue_from_lower.put([1, content1]) content2 = Content(res2[1].name, str(9)) self.thunklayer.queue_from_lower.put([1, content2]) res = self.thunklayer.queue_to_lower.get() c = Content(name, str(4)) self.assertEqual(res, [1, c])
def test_r2c_timeout_prevention(self): #todo same for rewrite """test r2c timeout prevention""" name1 = Name("/test1/NFN") name2 = Name("/test2/NFN") self.computationList.add_computation(name1, 0, Interest(name1)) self.computationList.add_computation(name2, 0, Interest(name2)) requestname1 = Name("/request1/NFN") requestname2 = Name("/request2/NFN") self.computationList.add_awaiting_data(name1, requestname1) self.computationList.add_awaiting_data(name2, requestname2) entry1 = self.computationList.get_computation(name1) self.computationList.remove_computation(name1) entry1.timeout = 1 self.computationList.append_computation(entry1) entry2 = self.computationList.get_computation(name2) self.computationList.remove_computation(name2) entry2.timeout = 1 self.computationList.append_computation(entry2) #ask for requests time.sleep(1) request_list = self.computationList.ageing() self.assertEqual(request_list, ([requestname1, self.r2cclient.R2C_create_message(requestname1), requestname2, self.r2cclient.R2C_create_message(requestname2)], [])) self.computationList.push_data(Content(self.r2cclient.R2C_create_message(requestname1))) time.sleep(1) request_list = self.computationList.ageing() self.assertEqual(request_list, ([requestname1, self.r2cclient.R2C_create_message(requestname1)], [name2]))
def test_simple_call_no_params_no_fib(self): """Test, if ToDataFirstOptimizer works correctly with a single function call without parameter without fib""" workflow = "/func/f1()" ast = self.parser.parse(workflow) self.assertFalse(self.optimizer.compute_fwd(None, ast, Interest(workflow))) self.assertTrue(self.optimizer.compute_local(None, ast, Interest(workflow))) rules = self.optimizer.rewrite(None, ast) self.assertEqual(rules, ['local'])
def main(args): # Packet encoder encoder = NdnTlvEncoder( ) if args.format == 'ndntlv' else SimpleStringEncoder # Generate interest packet first_interest: Interest = Interest(args.name) encoded_first_interest = encoder.encode(first_interest) # Send interest packet sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(5) sock.bind(("0.0.0.0", 0)) try: resolved_hostname = socket.gethostbyname(args.ip) except: print("Resolution of hostname failed.") sys.exit(-2) sock.sendto(encoded_first_interest, (resolved_hostname, args.port)) # Receive content object try: wire_packet_first, addr = sock.recvfrom(8192) except: print("Timeout.") sys.exit(-1) # Wait time_to_wait = int(encoder.decode_data(wire_packet_first)[1]) print("Waiting for result: " + str(time_to_wait)) time.sleep(time_to_wait * 1.2) # Send second interest new_components = args.name.split("/")[1:-1] new_components.append("resultpNFN") new_name = "/" + '/'.join(new_components) second_interest: Interest = Interest(new_name) encoded_second_interest = encoder.encode(second_interest) sock.sendto(encoded_second_interest, (resolved_hostname, args.port)) # Receive result try: wire_packet_second, addr = sock.recvfrom(8192) except: print("Timeout.") sys.exit(-1) # Print if args.plain is False: printer = NdnTlvPrinter(wire_packet_second) printer.formatted_print() else: encoder = NdnTlvEncoder() if encoder.is_content(wire_packet_second): sys.stdout.buffer.write( encoder.decode_data(wire_packet_second)[1] + b"\n") else: sys.exit(-2)
def test_add_to_await_list(self): """test adding data to the await list""" name = Name("/test") name2 = Name("/data") self.computationList.add_computation(name, 0, Interest(name)) self.computationList.add_computation(name2, 0, Interest(name2)) self.computationList.add_awaiting_data(name, Name("/request")) self.assertEqual(self.computationList.get_computation(name).awaiting_data, [Name("/request")]) self.assertEqual(self.computationList.get_computation(name2).awaiting_data, [])
def test_computation_table_ageing_nfn_requests_and_ready_computations( self): """test the ageing of the computation table using nfn requests and check ready computations""" name = Name("/test/NFN") name2 = Name("/data/NFN") self.computationList.add_computation(name, 0, Interest(name)) self.computationList.add_computation(name2, 0, Interest(name2)) self.computationList.container[0].timeout = 1.0 self.computationList.container[1].timeout = 1.0 request_name = Name("/request/NFN") request_name1 = Name("/request1/NFN") request_name2 = Name("/request2/NFN") self.computationList.container[0].add_name_to_await_list(request_name) self.computationList.container[0].add_name_to_await_list(request_name1) self.computationList.container[1].add_name_to_await_list(request_name2) self.assertEqual(len(self.computationList.container), 2) self.assertEqual(len(self.computationList.container[0].awaiting_data), 2) self.assertEqual(len(self.computationList.container[1].awaiting_data), 1) res = self.computationList.ageing() self.assertEqual(res, ([], [])) time.sleep(2) res = self.computationList.ageing() self.assertEqual(len(self.computationList.container), 2) self.assertEqual(len(self.computationList.container[0].awaiting_data), 2) # four since r2c self.assertEqual(len(self.computationList.container[1].awaiting_data), 1) # two since r2c self.assertEqual(self.computationList.container[0].awaiting_data, [ NFNAwaitListEntry(request_name), NFNAwaitListEntry(request_name1), ]) self.assertEqual(res, ([request_name, request_name1, request_name2], [])) self.computationList.push_data(Content(request_name)) ready_comps = self.computationList.get_ready_computations() self.assertEqual(ready_comps, []) v = self.computationList.push_data(Content(request_name1)) self.assertTrue(v) ready_comps = self.computationList.get_ready_computations() self.assertEqual(len(ready_comps), 1) self.assertEqual(ready_comps[0].original_name, name)
def test_interest_fwd_comp_simple_interest(self): """Test the edgecomputing forwarder with an simple interest""" cmp_name = Name("/func/f1") cmp_name += "_()" cmp_name += "NFN" workflow = "/func/f1()" ast = self.parser.parse(workflow) self.assertTrue(self.optimizer.compute_fwd(cmp_name, ast, Interest(cmp_name))) self.assertTrue(self.optimizer.compute_local(cmp_name, ast, Interest(cmp_name))) rules = self.optimizer.rewrite(cmp_name, ast) self.assertEqual(rules, [])
def test_update_status(self): """Test updating the status of a computation""" name = Name("/test") name2 = Name("/data") self.computationList.add_computation(name, 0, Interest(name)) self.computationList.add_computation(name2, 1, Interest(name2)) self.assertEqual(self.computationList.container[0].comp_state, NFNComputationState.START) self.assertEqual(self.computationList.container[1].comp_state, NFNComputationState.START) self.computationList.update_status(name, NFNComputationState.FWD) self.assertEqual(self.computationList.get_computation(name).comp_state, NFNComputationState.FWD) self.assertEqual(self.computationList.get_computation(name2).comp_state, NFNComputationState.START)
def test_remove_computation(self): """Test removing a computation from the container""" name = Name("/test") name2 = Name("/data") self.computationList.add_computation(name, 0, Interest(name)) self.computationList.add_computation(name2, 1, Interest(name2)) self.assertEqual(len(self.computationList.container), 2) self.computationList.remove_computation(Name("/test")) self.assertEqual(len(self.computationList.container), 1) self.assertEqual(self.computationList.container[0].original_name, name2)
def test_keep_alive_request(self): """test replying a incoming keep alive request""" interest = Interest("/test/func/_()/NFN") keep_alive = Interest("/test/func/_()/KEEPALIVE/NFN") content = Content(keep_alive.name) self.timeoutPreventionLayer.computation_table.add_computation(interest.name, 3, interest) self.timeoutPreventionLayer.queue_from_lower.put([3, keep_alive]) self.assertTrue(self.timeoutPreventionLayer.queue_to_higher.empty()) res = self.timeoutPreventionLayer.queue_to_lower.get(timeout=2.0) self.assertEqual(res, [3, content])
def test_metadata_from_lower_layer(self): """test receiving metadata from lower layer""" self.chunkLayer.start_process() md1_n = Name("/test/data") md1 = Content( md1_n, "mdo:/test/data/c0;/test/data/c1;/test/data/c2;/test/data/c3:/test/data/m1" ) md2_n = Name("/test/data/m1") md2 = Content(md2_n, "mdo:/test/data/c4:") self.chunkLayer._request_table.append(RequestTableEntry(md1_n)) self.chunkLayer.queue_from_lower.put([0, md1]) data = self.chunkLayer.queue_to_lower.get() self.assertEqual(Interest(md2_n), data[1]) chunknames = [ Name("/test/data/c0"), Name("/test/data/c1"), Name("/test/data/c2"), Name("/test/data/c3"), Name("/test/data/c4") ] for i in range(0, 4): data = self.chunkLayer.queue_to_lower.get() self.assertEqual(Interest(chunknames[i]), data[1]) self.assertTrue(self.chunkLayer.queue_to_lower.empty()) request: RequestTableEntry = self.chunkLayer.get_request_table_entry( md1_n) self.assertEqual(request.requested_chunks, chunknames[:4]) self.assertEqual(request.requested_md[0], md2_n) self.chunkLayer.queue_from_lower.put([0, md2]) try: data = self.chunkLayer.queue_to_lower.get(timeout=2.0) except: self.fail() self.assertEqual(data[1], Interest(chunknames[4])) self.assertTrue(self.chunkLayer.queue_to_lower.empty()) time.sleep(1) request: RequestTableEntry = self.chunkLayer.get_request_table_entry( md1_n) self.assertEqual(len(request.requested_md), 0) self.assertEqual(len(request.requested_chunks), 5) self.assertEqual(request.requested_chunks, chunknames)
def test_interest_passed_down_after_advertisement(self): """ Test that held interests are passed downwards once a forwarder advertisement with a matching route is received. """ waittime = 3.0 self.autoconflayer.start_process() # Create some test interests, two with the advertised prefix, and one with another foobar = Interest(Name('/foo/bar')) foobaz = Interest(Name('/foo/bar')) barfoo = Interest(Name('/bar/foo')) self.queue_from_higher.put([None, foobar]) self.queue_from_higher.put([None, foobaz]) self.queue_from_higher.put([None, barfoo]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the broadcast face was actually created and get its face id bcfid = self.faceidtable.get_or_create_faceid( AddressInfo(('127.255.255.255', 4242), 0)) self.assertIsNotNone(bcfid) # Make sure a forwarder solicitation was sent downwards solictiation = Interest(Name('/autoconfig/forwarders')) self.assertIn([bcfid, solictiation], tolower) # Create a forwarder advertisement and pass it to the autoconfig layer advertisement = Content(Name('/autoconfig/forwarders'), 'udp4://127.13.37.42:1234\nr:/foo\n') self.queue_from_lower.put([bcfid, advertisement]) # Catch all data the autoconfig layer sends downwards for 3 seconds deadline = datetime.utcnow() + timedelta(seconds=waittime) tolower = [] while datetime.utcnow() < deadline: try: data = self.queue_to_lower.get(timeout=waittime / 10) tolower.append(data) except queue.Empty: pass # Make sure the face to the forwarder was actually created and get its face id fwdfid = self.faceidtable.get_face_id( AddressInfo(('127.13.37.42', 1234), 0)) self.assertIsNotNone(fwdfid) # Make sure the two interests with matching prefixes were passed downwards self.assertIn([fwdfid, foobar], tolower) self.assertIn([fwdfid, foobaz], tolower) self.assertNotIn([fwdfid, barfoo], tolower)
def test_append_computation(self): """Test appending a computation""" name = Name("/test") name2 = Name("/data") self.computationList.add_computation(name, 0, Interest(name)) self.computationList.add_computation(name2, 1, Interest(name2)) self.assertEqual(len(self.computationList.container), 2) comp = self.computationList.get_computation(name) self.computationList.remove_computation(name) self.assertEqual(len(self.computationList.container), 1) self.computationList.append_computation(comp) self.assertEqual(len(self.computationList.container), 2) self.assertEqual(self.computationList.container[0].original_name, name2) self.assertEqual(self.computationList.container[1].original_name, name)