Skip to content

Commit

Permalink
GitHub issue #782 reproduction
Browse files Browse the repository at this point in the history
  • Loading branch information
adaszko committed Nov 26, 2021
1 parent 4ad4f35 commit 910e1a1
Show file tree
Hide file tree
Showing 108 changed files with 578 additions and 0 deletions.
1 change: 1 addition & 0 deletions e2e-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
workdir/replicator/
3 changes: 3 additions & 0 deletions e2e-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
1. [Install Poetry](https://python-poetry.org/docs/#installation)
1. In the `e2e-tests` subdirectory, run `poetry install`
1. You can run a particular end-to-end test by executing a command in the `e2e-tests` subdirectory: with `poetry run ./issue782.py`
147 changes: 147 additions & 0 deletions e2e-tests/issue782.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/usr/bin/env python3

import os
import sys
import json
import shlex
import pathlib
import contextlib
import subprocess
from typing import List

import trio
import colorama
from colorama import Fore


BOOTSTRAP_COLOR = Fore.WHITE
REPLICATOR_COLOR = Fore.YELLOW


class OrgNodeError(RuntimeError):
pass


# The default context manager for trio.Process waits until the process finishes whereas we want to terminate it ourselves.
@contextlib.asynccontextmanager
async def org_node_process(org_node_cmd: List[str]) -> trio.Process:
process = await trio.open_process(org_node_cmd, stdout=subprocess.PIPE)
try:
yield process
finally:
process.terminate()


async def org_node_log_entries(process: trio.Process):
async for chunk in process.stdout:
lines = chunk.split(b'\n')
for line in lines:
if line == b'':
continue
entry = json.loads(line)
yield entry


async def bootstrap_process(process: trio.Process, bootstrap_ready_event: trio.Event, cancel_scope: trio.CancelScope) -> None:
expected = """
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/heads/master" -> acce81a6568ec4342586a71a314485408c264068
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/remotes/hyn9diwfnytahjq8u3iw63h9jte1ydcatxax3saymwdxqu1zo645pe/heads/master" -> acce81a6568ec4342586a71a314485408c264068
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/HEAD" -> "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/heads/master"
"""
expected_lines = set(l for l in expected.split('\n') if l)
remaining_expected_lines = len(expected_lines)
async for entry in org_node_log_entries(process):
sys.stdout.buffer.write(BOOTSTRAP_COLOR.encode() + json.dumps(entry).encode() + Fore.RESET.encode() + b'\n')
sys.stdout.flush()
if entry['severity'] == 'ERROR':
raise OrgNodeError(entry['message'])
if entry['message'] in expected_lines:
remaining_expected_lines -= 1
if remaining_expected_lines == 0:
bootstrap_ready_event.set()
cancel_scope.cancel()


async def replicator_process(process: trio.Process, bootstrap_ready_event: trio.Event, cancel_scope: trio.CancelScope) -> None:
expected = """
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/heads/master" -> acce81a6568ec4342586a71a314485408c264068
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/remotes/hyn9diwfnytahjq8u3iw63h9jte1ydcatxax3saymwdxqu1zo645pe/heads/master" -> acce81a6568ec4342586a71a314485408c264068
Setting ref "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/HEAD" -> "refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/heads/master"
"""
expected_lines = set(l for l in expected.split('\n') if l)
remaining_expected_lines = len(expected_lines)
async for entry in org_node_log_entries(process):
sys.stdout.buffer.write(REPLICATOR_COLOR.encode() + json.dumps(entry).encode() + Fore.RESET.encode() + b'\n')
sys.stdout.flush()
if entry['severity'] == 'ERROR':
raise OrgNodeError(entry['message'])
if entry['message'] in expected_lines:
remaining_expected_lines -= 1
if remaining_expected_lines == 0:
break
cancel_scope.cancel()


def make_shell_command(shell_words: List[str]) -> str:
return ' '.join(shlex.quote(shell_word) for shell_word in shell_words)


async def async_main(org_node_executable_path: pathlib.Path, workdir_path: pathlib.Path) -> None:
bootstrap_workdir_path = workdir_path / 'bootstrap'
bootstrap_identity_path = bootstrap_workdir_path / 'identity'
bootstrap_git_path = bootstrap_workdir_path / 'git'
bootstrap_node_cmd = [
str(org_node_executable_path),
'--subgraph', 'https://api.thegraph.com/subgraphs/name/radicle-dev/radicle-orgs',
'--rpc-url', 'wss://eth-rinkeby.alchemyapi.io/v2/1T6h-0rxu7SRzKEtmukIoxaJOXazLDNs',
'--identity', str(bootstrap_identity_path),
'--root', str(bootstrap_workdir_path),
'--orgs', '0x0000000000000000000000000000000000000000',
'--urns', 'rad:git:hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto',
'--listen', '127.0.0.1:8776',
'--web-server-listen', '127.0.0.1:8336',
'--log-format', 'gcp',
]
print('Bootstrap node command:', make_shell_command(bootstrap_node_cmd))

replicator_workdir_path = workdir_path / 'replicator'
replicator_identity_path = replicator_workdir_path / 'identity'
replicator_git_path = replicator_workdir_path / 'git'
replicator_node_cmd = [
str(org_node_executable_path),
'--subgraph', 'https://api.thegraph.com/subgraphs/name/radicle-dev/radicle-orgs',
'--rpc-url', 'wss://eth-rinkeby.alchemyapi.io/v2/1T6h-0rxu7SRzKEtmukIoxaJOXazLDNs',
'--identity', str(replicator_identity_path),
'--root', str(replicator_workdir_path),
'--orgs', '0x0000000000000000000000000000000000000000',
'--urns', 'rad:git:hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto',
'--bootstrap', '[email protected]:8776',
'--listen', '127.0.0.1:8777',
'--web-server-listen', '127.0.0.1:8337',
'--log-format', 'gcp',
]
print('Replicator node command:', make_shell_command(replicator_node_cmd))

os.environ['RUST_LOG'] = 'DEBUG'
async with org_node_process(bootstrap_node_cmd) as bootstrap:
bootstrap_ready_event = trio.Event()
async with trio.open_nursery() as nursery:
nursery.start_soon(bootstrap_process, bootstrap, bootstrap_ready_event, nursery.cancel_scope)
await bootstrap_ready_event.wait()
async with org_node_process(replicator_node_cmd) as replicator:
await replicator_process(replicator, bootstrap_ready_event, nursery.cancel_scope)

assert bootstrap_git_path.joinpath('refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/remotes/hyn9diwfnytahjq8u3iw63h9jte1ydcatxax3saymwdxqu1zo645pe/heads/master').is_file()
assert replicator_git_path.joinpath('refs/namespaces/hnrkbtw9t1of4ykjy6er4qqwxtc54k9943eto/refs/remotes/hyn9diwfnytahjq8u3iw63h9jte1ydcatxax3saymwdxqu1zo645pe/heads/master').is_file()



def main():
org_node_executable_path = pathlib.Path(__file__).parent.parent.absolute().joinpath('target/debug/radicle-org-node')
workdir_path = pathlib.Path(__file__).parent.joinpath('workdir').absolute()
trio.run(async_main, org_node_executable_path, workdir_path)



if __name__ == '__main__':
sys.exit(main())
Loading

0 comments on commit 910e1a1

Please sign in to comment.