From c472f3ea46a5dd5f62bb12b5857e779ae0d74dc5 Mon Sep 17 00:00:00 2001 From: William Boman Date: Sat, 16 Apr 2022 01:43:09 +0200 Subject: fix(async): slightly better support for nested coroutine contexts (#600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(async): only dispatch first failure in a.wait_all * add InstallContext:run_concurrently This is needed due to how multiple coroutine contexts are used in a hierchical structure, and the async coroutine dispatcher loses this hierchical context inside callback functions invoked via FFI (I… assume?). --- tests/core/async/async_spec.lua | 20 ++++++++++++------- tests/core/installer_spec.lua | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) (limited to 'tests/core') diff --git a/tests/core/async/async_spec.lua b/tests/core/async/async_spec.lua index 9795adce..c0e8992e 100644 --- a/tests/core/async/async_spec.lua +++ b/tests/core/async/async_spec.lua @@ -136,22 +136,28 @@ describe("async", function() "should run all suspending functions concurrently", async_test(function() local start = timestamp() - local function sleep(ms) + local function sleep(ms, ret_val) return function() a.sleep(ms) + return ret_val end end - a.wait_all { - sleep(100), - sleep(100), - sleep(100), - sleep(100), - sleep(100), + local one, two, three, four, five = a.wait_all { + sleep(100, 1), + sleep(100, "two"), + sleep(100, "three"), + sleep(100, 4), + sleep(100, 5), } local grace = 50 local delta = timestamp() - start assert.is_true(delta <= (100 + grace)) assert.is_true(delta >= (100 - grace)) + assert.equals(1, one) + assert.equals("two", two) + assert.equals("three", three) + assert.equals(4, four) + assert.equals(5, five) end) ) end) diff --git a/tests/core/installer_spec.lua b/tests/core/installer_spec.lua index 75911416..cf8e8795 100644 --- a/tests/core/installer_spec.lua +++ b/tests/core/installer_spec.lua @@ -1,11 +1,17 @@ local spy = require "luassert.spy" local match = require "luassert.match" local fs = require "nvim-lsp-installer.core.fs" +local a = require "nvim-lsp-installer.core.async" local installer = require "nvim-lsp-installer.core.installer" local InstallContext = require "nvim-lsp-installer.core.installer.context" local process = require "nvim-lsp-installer.process" local Optional = require "nvim-lsp-installer.core.optional" +local function timestamp() + local seconds, microseconds = vim.loop.gettimeofday() + return (seconds * 1000) + math.floor(microseconds / 1000) +end + describe("installer", function() it( "should call installer", @@ -89,4 +95,42 @@ describe("installer", function() ) end) ) + + it( + "should run async functions concurrently", + async_test(function() + spy.on(fs, "write_file") + local destination_dir = ("%s/installer_spec_concurrent"):format(os.getenv "INSTALL_ROOT_DIR") + local ctx = InstallContext.new { + name = "installer_spec_receipt", + destination_dir = destination_dir, + boundary_path = os.getenv "INSTALL_ROOT_DIR", + stdio_sink = process.empty_sink(), + requested_version = Optional.empty(), + } + local capture = spy.new() + local start = timestamp() + installer.run_installer(ctx, function(c) + capture(c:run_concurrently { + function() + a.sleep(100) + return installer.context() + end, + function() + a.sleep(100) + return "two" + end, + function() + a.sleep(100) + return "three" + end, + }) + c.receipt:with_primary_source(c.receipt.npm "my-pkg") + end) + local stop = timestamp() + local grace_ms = 25 + assert.is_true((stop - start) >= (100 - grace_ms)) + assert.spy(capture).was_called_with(match.is_ref(ctx), "two", "three") + end) + ) end) -- cgit v1.2.3-70-g09d2