From 6de63f1b3b2e5cee5b5398a9f8a193586b042260 Mon Sep 17 00:00:00 2001 From: David Brochart Date: Mon, 12 Feb 2024 11:12:17 +0100 Subject: [PATCH 1/2] Drop YTest --- tests/test_pycrdt_yjs.py | 78 +++++++++++++++++++--------------------- tests/yjs_client_0.js | 34 +++++++----------- tests/yjs_client_1.js | 30 +++++----------- 3 files changed, 57 insertions(+), 85 deletions(-) diff --git a/tests/test_pycrdt_yjs.py b/tests/test_pycrdt_yjs.py index 9e438a5..b9ca140 100644 --- a/tests/test_pycrdt_yjs.py +++ b/tests/test_pycrdt_yjs.py @@ -1,75 +1,69 @@ +from __future__ import annotations + +from functools import partial + import pytest -from anyio import Event, create_task_group, move_on_after, sleep +from anyio import Event, fail_after from pycrdt import Array, Doc, Map from websockets import connect from pycrdt_websocket import WebsocketProvider -class YTest: - def __init__(self, ydoc: Doc, timeout: float = 1.0): - self.ydoc = ydoc +class Change: + def __init__(self, event, timeout, ydata, sid, key): + self.event = event self.timeout = timeout - self.ydoc["_test"] = self.ytest = Map() - self.clock = -1.0 + self.ydata = ydata + self.sid = sid + self.key = key - def run_clock(self): - self.clock = max(self.clock, 0.0) - self.ytest["clock"] = self.clock + async def wait(self): + with fail_after(self.timeout): + await self.event.wait() + self.ydata.unobserve(self.sid) + if self.key is None: + return + return self.ydata[self.key] - async def clock_run(self): - change = Event() - def callback(event): - if "clock" in event.keys: - clk = event.keys["clock"]["newValue"] - if clk > self.clock: - self.clock = clk + 1.0 - change.set() +def callback(change_event, key, event): + if key is None or key in event.keys: + change_event.set() - subscription_id = self.ytest.observe(callback) - async with create_task_group(): - with move_on_after(self.timeout): - await change.wait() - self.ytest.unobserve(subscription_id) +def watch(ydata, key: str | None = None, timeout: float = 1.0): + change_event = Event() + sid = ydata.observe(partial(callback, change_event, key)) + return Change(change_event, timeout, ydata, sid, key) @pytest.mark.anyio @pytest.mark.parametrize("yjs_client", "0", indirect=True) async def test_pycrdt_yjs_0(yws_server, yjs_client): ydoc = Doc() - ytest = YTest(ydoc) async with connect("ws://127.0.0.1:1234/my-roomname") as websocket, WebsocketProvider( ydoc, websocket ): ydoc["map"] = ymap = Map() - # set a value in "in" for v_in in range(10): ymap["in"] = float(v_in) - ytest.run_clock() - await ytest.clock_run() - v_out = ymap["out"] + v_out = await watch(ymap, "out").wait() assert v_out == v_in + 1.0 @pytest.mark.anyio @pytest.mark.parametrize("yjs_client", "1", indirect=True) async def test_pycrdt_yjs_1(yws_server, yjs_client): - # wait for the JS client to connect - tt, dt = 0, 0.1 - while True: - await sleep(dt) - if "/my-roomname" in yws_server.rooms: - break - tt += dt - if tt >= 1: - raise RuntimeError("Timeout waiting for client to connect") - ydoc = yws_server.rooms["/my-roomname"].ydoc - ytest = YTest(ydoc) - ytest.run_clock() - await ytest.clock_run() + ydoc = Doc() ydoc["cells"] = ycells = Array() ydoc["state"] = ystate = Map() - assert ycells.to_py() == [{"metadata": {"foo": "bar"}, "source": "1 + 2"}] - assert ystate.to_py() == {"state": {"dirty": False}} + ycells_change = watch(ycells) + ystate_change = watch(ystate) + async with connect("ws://127.0.0.1:1234/my-roomname") as websocket, WebsocketProvider( + ydoc, websocket + ): + await ycells_change.wait() + await ystate_change.wait() + assert ycells.to_py() == [{"metadata": {"foo": "bar"}, "source": "1 + 2"}] + assert ystate.to_py() == {"state": {"dirty": False}} diff --git a/tests/yjs_client_0.js b/tests/yjs_client_0.js index 3e8f7a6..92c87c0 100644 --- a/tests/yjs_client_0.js +++ b/tests/yjs_client_0.js @@ -1,32 +1,24 @@ const Y = require('yjs') const WebsocketProvider = require('y-websocket').WebsocketProvider +const ws = require('ws') const ydoc = new Y.Doc() -const ytest = ydoc.getMap('_test') const ymap = ydoc.getMap('map') -const ws = require('ws') + +function increment(resolve) { + ymap.set('out', ymap.get('in') + 1); + resolve(); +} + +ymap.observe(event => { + if (event.transaction.local || !event.changes.keys.has('in')) { + return + } + new Promise(increment); +}) const wsProvider = new WebsocketProvider( 'ws://127.0.0.1:1234', 'my-roomname', ydoc, { WebSocketPolyfill: ws } ) - -wsProvider.on('status', event => { - console.log(event.status) -}) - -var clock = -1 - -ytest.observe(event => { - event.changes.keys.forEach((change, key) => { - if (key === 'clock') { - const clk = ytest.get('clock') - if (clk > clock) { - ymap.set('out', ymap.get('in') + 1) - clock = clk + 1 - ytest.set('clock', clock) - } - } - }) -}) diff --git a/tests/yjs_client_1.js b/tests/yjs_client_1.js index 655331d..cb743ea 100644 --- a/tests/yjs_client_1.js +++ b/tests/yjs_client_1.js @@ -1,11 +1,8 @@ const Y = require('yjs') const WebsocketProvider = require('y-websocket').WebsocketProvider +const ws = require('ws') const ydoc = new Y.Doc() -const ytest = ydoc.getMap('_test') -const ycells = ydoc.getArray("cells") -const ystate = ydoc.getMap("state") -const ws = require('ws') const wsProvider = new WebsocketProvider( 'ws://127.0.0.1:1234', 'my-roomname', @@ -13,23 +10,12 @@ const wsProvider = new WebsocketProvider( { WebSocketPolyfill: ws } ) -wsProvider.on('status', event => { - console.log(event.status) -}) - -var clock = -1 +wsProvider.on('sync', () => { + const ycells = ydoc.getArray('cells') + const ystate = ydoc.getMap('state') -ytest.observe(event => { - event.changes.keys.forEach((change, key) => { - if (key === 'clock') { - const clk = ytest.get('clock') - if (clk > clock) { - const cells = [new Y.Map([['source', new Y.Text('1 + 2')], ['metadata', {'foo': 'bar'}]])] - ycells.push(cells) - ystate.set('state', {'dirty': false}) - clock = clk + 1 - ytest.set('clock', clock) - } - } - }) + const cells = [new Y.Map([['source', new Y.Text('1 + 2')], ['metadata', {'foo': 'bar'}]])] + const state = {'dirty': false} + ycells.push(cells) + ystate.set('state', state) }) From dad824cb00b457f3ffffb1890ae1473398e2595d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:13:08 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_pycrdt_yjs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_pycrdt_yjs.py b/tests/test_pycrdt_yjs.py index b9ca140..bd0e8c3 100644 --- a/tests/test_pycrdt_yjs.py +++ b/tests/test_pycrdt_yjs.py @@ -33,9 +33,9 @@ def callback(change_event, key, event): def watch(ydata, key: str | None = None, timeout: float = 1.0): - change_event = Event() - sid = ydata.observe(partial(callback, change_event, key)) - return Change(change_event, timeout, ydata, sid, key) + change_event = Event() + sid = ydata.observe(partial(callback, change_event, key)) + return Change(change_event, timeout, ydata, sid, key) @pytest.mark.anyio