def test_occupancy_and_state_destruction(self): for _ in range (0,100): c1 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) # load a file hello_file = file_dir.joinpath('hello.txt') self.assertTrue(False if not hello_file.is_file() else True) uid1 = c1.send_command("load", {"file path": str(hello_file), "state": None}) actual1 = c1.wait_for_reply_to(uid1) self.assertIn('result', actual1) self.assertIn('state', actual1['result']) state1 = actual1['result']['state']
class LowLevelCryptolApiTests(unittest.TestCase): c = None @classmethod def setUpClass(self): if (command := os.getenv('CRYPTOL_SERVER')) is not None and ( command := find_executable(command)) is not None: self.c = argo.ServerConnection( argo.DynamicSocketProcess(command + " socket")) elif (url := os.getenv('CRYPTOL_SERVER_URL')) is not None: self.c = argo.ServerConnection(argo.HttpProcess(url))
def setUpClass(self): p = subprocess.Popen( ["cabal", "run", "exe:file-echo-api", "--verbose=0", "--", "http", "/", "--port", self.port, "--log", HttpTests.server_log_file()], stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE, start_new_session=True) time.sleep(3) assert(p is not None) poll_result = p.poll() if poll_result is not None: print(poll_result) print(p.stdout.read()) print(p.stderr.read()) assert(poll_result is None) self.p = p self.c = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/'))
def setUpClass(self): p = subprocess.Popen([ "cabal", "run", "exe:mutable-file-echo-api", "--verbose=0", "--", "--max-occupancy", "2", "http", "/", "--port", "8080" ], stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE, start_new_session=True) time.sleep(3) assert (p is not None) poll_result = p.poll() if poll_result is not None: print(poll_result) print(p.stdout.read()) print(p.stderr.read()) assert (poll_result is None) self.p = p self.other_c = argo.ServerConnection( argo.HttpProcess('http://localhost:8080/'))
def setUpClass(self): os.system('openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr'\ + ' -subj "/C=GB/ST=London/L=London/O=Acme Widgets/OU=IT Department/CN=localhost"') os.system('openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt') p = subprocess.Popen( ["cabal", "run", "exe:file-echo-api", "--verbose=0", "--", "http", "/" , "--port", self.port, "--tls", "--log", TLSTests2.server_log_file()], stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.PIPE, start_new_session=True) time.sleep(3) assert(p is not None) poll_result = p.poll() if poll_result is not None: print(poll_result) print(p.stdout.read()) print(p.stderr.read()) assert(poll_result is None) self.p = p self.c = argo.ServerConnection(argo.HttpProcess(f'https://localhost:{self.port}', verify=False))
def test_interrupts(self): c1 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) c2 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) # load a file hello_file = file_dir.joinpath('hello.txt') self.assertTrue(False if not hello_file.is_file() else True) uid1 = c1.send_command("load", {"file path": str(hello_file), "state": None}) uid2 = c2.send_command("load", {"file path": str(hello_file), "state": None}) actual1 = c1.wait_for_reply_to(uid1) self.assertIn('result', actual1) self.assertIn('state', actual1['result']) state1 = actual1['result']['state'] actual2 = c2.wait_for_reply_to(uid2) self.assertIn('result', actual2) self.assertIn('state', actual2['result']) state2 = actual2['result']['state'] # simple sleep for 3 seconds t1 = time.time() three_seconds = 3000000 uid1 = c1.send_query("sleep query", {"microseconds": three_seconds, "state": state1}) actual1 = c1.wait_for_reply_to(uid1) t2 = time.time() self.assertIn('result', actual1) if 'result' in actual1: self.assertIn('state', actual1['result']) self.assertIn('answer', actual1['result']) if 'answer' in actual1['result']: self.assertIn('value', actual1['result']['answer']) if 'value' in actual1['result']['answer']: self.assertGreater(actual1['result']['answer']['value'], 2.9) self.assertGreater(t2 - t1, 2.9) # Sleep for 100 seconds, but then interrupt! newpid = os.fork() if newpid == 0: time.sleep(3) uid2 = c2.send_notification("interrupt", {}) os._exit(0) else: one_hundred_sec = 100000000 t1 = time.time() uid1 = c1.send_query("sleep query", {"microseconds": one_hundred_sec, "state": state1}) actual1 = c1.wait_for_reply_to(uid1) expected = {'error':{'data':{'stdout':None,'stderr':None},'code':24,'message':'Request interrupted'},'jsonrpc':'2.0','id':uid1} self.assertEqual(actual1, expected) # check contents...? uid1 = assertShow(self, c1, state=state1, expected='Hello World!\n') uid2 = assertShow(self, c2, state=state2, expected='Hello World!\n') # mutation/interrupt test newpid = os.fork() if newpid != 0: # parent tries to clean up two_sec = 2000000 t1 = time.time() uid1 = c1.send_command("slow clear", {"pause microseconds": two_sec, "state": state1}) actual1 = c1.wait_for_reply_to(uid1) expected = {'error':{'data':{'stdout':None,'stderr':None},'code':24,'message':'Request interrupted'},'jsonrpc':'2.0','id':uid1} self.assertEqual(actual1, expected) else: # child allows cleanup to start but not finish time.sleep(4) uid2 = c2.send_notification("interrupt", {}) os._exit(0) # check contents (N.B., there is no mutable state, so interrupts which stop a command mean # the state is not updated by the argo server backend). uid1 = assertShow(self, c1, state=state1, expected='Hello World!\n') uid2 = assertShow(self, c2, state=state2, expected='Hello World!\n') # Ensure sleeping notification delays the subsequent request # (i.e., requests can't interrupt or be interleaved with notification handling) six_seconds = three_seconds * 2 newpid = os.fork() if newpid == 0: uid2 = c1.send_notification("sleep notification", {"microseconds": six_seconds}) time.sleep(2) os._exit(0) else: t1 = time.time() time.sleep(2) uid2 = assertShow(self, c2, state=state2, expected='Hello World!\n') t2 = time.time() self.assertGreater(t2 - t1, 5.9)
def test_occupancy_and_state_destruction(self): c1 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) c2 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) # load a file hello_file = file_dir.joinpath('hello.txt') self.assertTrue(False if not hello_file.is_file() else True) uid1 = c1.send_command("load", {"file path": str(hello_file), "state": None}) uid2 = c2.send_command("load", {"file path": str(hello_file), "state": None}) actual1 = c1.wait_for_reply_to(uid1) self.assertIn('result', actual1) self.assertIn('state', actual1['result']) state1 = actual1['result']['state'] actual2 = c2.wait_for_reply_to(uid2) self.assertIn('result', actual2) self.assertIn('state', actual2['result']) state2 = actual2['result']['state'] # check the next (3rd) connection is rejected c3 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) uid3 = c3.send_command("load", {"file path": str(hello_file), "state": None}) actual3 = c3.wait_for_reply_to(uid3) expected = {'error':{'data':{'stdout':None,'stderr':None},'code':22,'message':'Server at max capacity'},'jsonrpc':'2.0','id':uid3} self.assertEqual(actual3, expected) # kill connection 1's state c1.send_notification("destroy state", {"state to destroy": state1}) # ensure connection 1's state is dead uid1 = c1.send_query("show", {"state": state1}) actual1 = c1.wait_for_reply_to(uid1) expected = {'error':{'data':{'stdout':None,'data':state1,'stderr':None},'code':20,'message':'Unknown state ID'},'jsonrpc':'2.0','id':uid1} self.assertEqual(actual1, expected) # now connection 3 should succeed uid3 = c3.send_command("load", {"file path": str(hello_file), "state": None}) actual3 = c3.wait_for_reply_to(uid3) self.assertIn('result', actual3) self.assertIn('state', actual3['result']) state3 = actual3['result']['state'] # kill all the connection's state c1.send_notification("destroy all states", {}) # ensure connection 2's state is dead uid2 = c2.send_query("show", {"state": state2}) actual2 = c2.wait_for_reply_to(uid2) expected = {'error':{'data':{'stdout':None,'data':state2,'stderr':None},'code':20,'message':'Unknown state ID'},'jsonrpc':'2.0','id':uid2} self.assertEqual(actual2, expected) # ensure connection 3's state is dead uid3 = c3.send_query("show", {"state": state3}) actual3 = c3.wait_for_reply_to(uid3) expected = {'error':{'data':{'stdout':None,'data':state3,'stderr':None},'code':20,'message':'Unknown state ID'},'jsonrpc':'2.0','id':uid3} self.assertEqual(actual3, expected) # now ensure there's room for two more new connections uid1 = c1.send_command("load", {"file path": str(hello_file), "state": None}) uid2 = c2.send_command("load", {"file path": str(hello_file), "state": None}) actual1 = c1.wait_for_reply_to(uid1) self.assertIn('result', actual1) self.assertIn('state', actual1['result']) state1 = actual1['result']['state'] actual2 = c2.wait_for_reply_to(uid2) self.assertIn('result', actual2) self.assertIn('state', actual2['result']) state2 = actual2['result']['state'] # check again that the next (3rd) connection is rejected c3 = argo.ServerConnection(argo.HttpProcess(f'http://localhost:{self.port}/')) uid3 = c3.send_command("load", {"file path": str(hello_file), "state": None}) actual3 = c3.wait_for_reply_to(uid3) expected = {'error':{'data':{'stdout':None,'stderr':None},'code':22,'message':'Server at max capacity'},'jsonrpc':'2.0','id':uid3} self.assertEqual(actual3, expected)
def test_interrupts(self): c1 = argo.ServerConnection(argo.HttpProcess('http://localhost:8083/')) c2 = argo.ServerConnection(argo.HttpProcess('http://localhost:8083/')) # load a file hello_file = file_dir.joinpath('hello.txt') self.assertTrue(False if not hello_file.is_file() else True) uid1 = c1.send_command("load", { "file path": str(hello_file), "state": None }) uid2 = c2.send_command("load", { "file path": str(hello_file), "state": None }) actual1 = c1.wait_for_reply_to(uid1) self.assertIn('result', actual1) self.assertIn('state', actual1['result']) state1 = actual1['result']['state'] actual2 = c2.wait_for_reply_to(uid2) self.assertIn('result', actual2) self.assertIn('state', actual2['result']) state2 = actual2['result']['state'] # simple sleep for 3 seconds t1 = time.time() uid1 = c1.send_query("sleep query", { "microseconds": 3000000, "state": state1 }) actual1 = c1.wait_for_reply_to(uid1) t2 = time.time() self.assertIn('result', actual1) if 'result' in actual1: self.assertIn('state', actual1['result']) self.assertIn('answer', actual1['result']) if 'answer' in actual1['result']: self.assertIn('value', actual1['result']['answer']) if 'value' in actual1['result']['answer']: self.assertGreater(actual1['result']['answer']['value'], 2.9) self.assertGreater(t2 - t1, 2.9) # sleep/interrupt test newpid = os.fork() if newpid != 0: # parent tries to sleep one_hundred_sec = 100000000 t1 = time.time() uid1 = c1.send_query("sleep query", { "microseconds": one_hundred_sec, "state": state1 }) t2 = time.time() else: # child does not allow sleep time.sleep(3) uid2 = c2.send_notification("interrupt", {}) os._exit(0) # check interrupt actually interrupted 100sec sleep self.assertLess(t2 - t1, 10) # mutation/interrupt test newpid = os.fork() if newpid != 0: # parent tries to clean up two_sec = 2000000 t1 = time.time() uid1 = c1.send_command("slow clear", { "pause microseconds": two_sec, "state": state1 }) else: # child allows cleanup to start but not finish time.sleep(4) uid2 = c2.send_notification("interrupt", {}) os._exit(0) # check contents (N.B., the mutable server uses an IORef for the # contents, so the interrupt doesn't prevent effects.) (uid1, state1) = assertShow(self, c1, state=state1, expected='Hello World!\n', expected_equal=False) (uid1, state1) = assertShow(self, c1, state=state1, expected='', expected_equal=False) (uid2, state2) = assertShow(self, c2, state=state2, expected='Hello World!\n')
def test_subsequent_connection(self): c = argo.ServerConnection(argo.HttpProcess('http://localhost:8080/')) ## Positive tests -- make sure the server behaves as we expect with valid RPCs # [c] Check that their is nothing to show if we haven't loaded a file yet (prev_uid, state) = assertShow(self, c, state=None, expected='') # [c] load a file hello_file = file_dir.joinpath('hello.txt') self.assertTrue(False if not hello_file.is_file() else True) uid = c.send_command("load", { "file path": str(hello_file), "state": state }) actual = c.wait_for_reply_to(uid) self.assertTrue('result' in actual and 'state' in actual['result']) state = actual['result']['state'] expected = { 'result': { 'state': state, 'stdout': '', 'stderr': '', 'answer': [] }, 'jsonrpc': '2.0', 'id': uid } self.assertEqual(actual, expected) self.assertNotEqual(uid, prev_uid) self.assertNotEqual(state, None) prev_uid = uid # [c] check the contents of the loaded file (prev_uid, state) = assertShow(self, c, state=state, expected='Hello World!\n') # [other_c] start a subsequent connection other_c = argo.ServerConnection( argo.HttpProcess('http://localhost:8080/')) # [other_c] check that the other connection has nothing to show if we haven't loaded our own file yet (other_prev_uid, other_state) = assertShow(self, other_c, state=None, expected='') # [other_c] load a file base_file = file_dir.joinpath('base.txt') other_uid = other_c.send_command("load", { "file path": str(base_file), "state": other_state }) actual = other_c.wait_for_reply_to(other_uid) self.assertTrue('result' in actual and 'state' in actual['result']) other_state = actual['result']['state'] expected = { 'result': { 'state': other_state, 'stdout': '', 'stderr': '', 'answer': [] }, 'jsonrpc': '2.0', 'id': other_uid } self.assertEqual(actual, expected) self.assertNotEqual(other_uid, other_prev_uid) self.assertNotEqual(other_state, None) other_prev_uid = other_uid # [other_c] clear the loaded file other_uid = other_c.send_command("clear", {"state": other_state}) actual = other_c.wait_for_reply_to(other_uid) self.assertTrue('result' in actual and 'state' in actual['result']) cleared_state = actual['result']['state'] expected = { 'result': { 'state': cleared_state, 'stdout': '', 'stderr': '', 'answer': [] }, 'jsonrpc': '2.0', 'id': other_uid } self.assertEqual(actual, expected) self.assertNotEqual(cleared_state, other_state) self.assertNotEqual(other_uid, other_prev_uid) # [c] check the contents of the loaded file again in the original connection (prev_uid, state) = assertShow(self, c, state=state, expected='Hello World!\n')