diff options
Diffstat (limited to 'nixpkgs/nixos/tests/matrix/appservice-irc.nix')
-rw-r--r-- | nixpkgs/nixos/tests/matrix/appservice-irc.nix | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/matrix/appservice-irc.nix b/nixpkgs/nixos/tests/matrix/appservice-irc.nix new file mode 100644 index 000000000000..78c53024ca6c --- /dev/null +++ b/nixpkgs/nixos/tests/matrix/appservice-irc.nix @@ -0,0 +1,225 @@ +import ../make-test-python.nix ({ pkgs, ... }: + let + homeserverUrl = "http://homeserver:8008"; + in + { + name = "matrix-appservice-irc"; + meta = { + maintainers = pkgs.matrix-appservice-irc.meta.maintainers; + }; + + nodes = { + homeserver = { pkgs, ... }: { + # We'll switch to this once the config is copied into place + specialisation.running.configuration = { + services.matrix-synapse = { + enable = true; + settings = { + database.name = "sqlite3"; + app_service_config_files = [ "/registration.yml" ]; + + enable_registration = true; + + # don't use this in production, always use some form of verification + enable_registration_without_verification = true; + + listeners = [ { + # The default but tls=false + bind_addresses = [ + "0.0.0.0" + ]; + port = 8008; + resources = [ { + "compress" = true; + "names" = [ "client" ]; + } { + "compress" = false; + "names" = [ "federation" ]; + } ]; + tls = false; + type = "http"; + } ]; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8008 ]; + }; + }; + + ircd = { pkgs, ... }: { + services.ngircd = { + enable = true; + config = '' + [Global] + Name = ircd.ircd + Info = Server Info Text + AdminInfo1 = _ + + [Channel] + Name = #test + Topic = a cool place + + [Options] + PAM = no + ''; + }; + networking.firewall.allowedTCPPorts = [ 6667 ]; + }; + + appservice = { pkgs, ... }: { + services.matrix-appservice-irc = { + enable = true; + registrationUrl = "http://appservice:8009"; + + settings = { + homeserver.url = homeserverUrl; + homeserver.domain = "homeserver"; + + ircService.servers."ircd" = { + name = "IRCd"; + port = 6667; + dynamicChannels = { + enabled = true; + aliasTemplate = "#irc_$CHANNEL"; + }; + }; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8009 ]; + }; + + client = { pkgs, ... }: { + environment.systemPackages = [ + (pkgs.writers.writePython3Bin "do_test" + { + libraries = [ pkgs.python3Packages.matrix-nio ]; + flakeIgnore = [ + # We don't live in the dark ages anymore. + # Languages like Python that are whitespace heavy will overrun + # 79 characters.. + "E501" + ]; + } '' + import sys + import socket + import functools + from time import sleep + import asyncio + + from nio import AsyncClient, RoomMessageText, JoinResponse + + + async def matrix_room_message_text_callback(matrix: AsyncClient, msg: str, _r, e): + print("Received matrix text message: ", e) + if msg in e.body: + print("Received hi from IRC") + await matrix.close() + exit(0) # Actual exit point + + + class IRC: + def __init__(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect(("ircd", 6667)) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + sock.send(b"USER bob bob bob :bob\n") + sock.send(b"NICK bob\n") + self.sock = sock + + def join(self, room: str): + self.sock.send(f"JOIN {room}\n".encode()) + + def privmsg(self, room: str, msg: str): + self.sock.send(f"PRIVMSG {room} :{msg}\n".encode()) + + def expect_msg(self, body: str): + buffer = "" + while True: + buf = self.sock.recv(1024).decode() + buffer += buf + if body in buffer: + return + + + async def run(homeserver: str): + irc = IRC() + + matrix = AsyncClient(homeserver) + response = await matrix.register("alice", "foobar") + print("Matrix register response: ", response) + + response = await matrix.join("#irc_#test:homeserver") + print("Matrix join room response:", response) + assert isinstance(response, JoinResponse) + room_id = response.room_id + + irc.join("#test") + # FIXME: what are we waiting on here? Matrix? IRC? Both? + # 10s seem bad for busy hydra machines. + sleep(10) + + # Exchange messages + print("Sending text message to matrix room") + response = await matrix.room_send( + room_id=room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": "hi from matrix"}, + ) + print("Matrix room send response: ", response) + irc.privmsg("#test", "hi from irc") + + print("Waiting for the matrix message to appear on the IRC side...") + irc.expect_msg("hi from matrix") + + callback = functools.partial( + matrix_room_message_text_callback, matrix, "hi from irc" + ) + matrix.add_event_callback(callback, RoomMessageText) + + print("Waiting for matrix message...") + await matrix.sync_forever() + + exit(1) # Unreachable + + + if __name__ == "__main__": + asyncio.run(run(sys.argv[1])) + '' + ) + ]; + }; + }; + + testScript = '' + import pathlib + import os + + start_all() + + ircd.wait_for_unit("ngircd.service") + ircd.wait_for_open_port(6667) + + with subtest("start the appservice"): + appservice.wait_for_unit("matrix-appservice-irc.service") + appservice.wait_for_open_port(8009) + + with subtest("copy the registration file"): + appservice.copy_from_vm("/var/lib/matrix-appservice-irc/registration.yml") + homeserver.copy_from_host( + str(pathlib.Path(os.environ.get("out", os.getcwd())) / "registration.yml"), "/" + ) + homeserver.succeed("chmod 444 /registration.yml") + + with subtest("start the homeserver"): + homeserver.succeed( + "/run/current-system/specialisation/running/bin/switch-to-configuration test >&2" + ) + + homeserver.wait_for_unit("matrix-synapse.service") + homeserver.wait_for_open_port(8008) + + with subtest("ensure messages can be exchanged"): + client.succeed("do_test ${homeserverUrl} >&2") + ''; + }) |