Skip to content

Commit

Permalink
test: improve language-server test resilience
Browse files Browse the repository at this point in the history
primarily by increasing timeouts, ensuring testclient and testlanguageserver is disposed properly, and adding missing conditionawaiters.

Likely still a testclient memory leak - see OmniSharp/csharp-language-server-protocol#1037
  • Loading branch information
chrissimon-au committed Nov 26, 2023
1 parent d524fc1 commit ee9aa75
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,20 @@ let tests =

let pathLoader () : obj = path

let loadingAwaiter = ConditionAwaiter.create ()

let config =
[ Workspace.optionsBuilder <| Path.Combine("fixtures", "completion_tests")
ConfigurationSection.contextivePathLoaderBuilder pathLoader ]
ConfigurationSection.contextivePathLoaderBuilder pathLoader
ServerLog.optionsBuilder loadingAwaiter ]

use! client = TestClient(config) |> init

path <- "two.yml"
ConfigurationSection.didChangePath client path

do! ServerLog.waitForLogMessage loadingAwaiter "Loading contextive" |> Async.Ignore

let! labels = Completion.getCompletionLabels client

test <@ (labels, Fixtures.Two.expectedCompletionLabels) ||> Seq.compareWith compare = 0 @>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let tests =
[ Workspace.optionsBuilder ""
ConfigurationSection.contextivePathBuilder pathValue ]

let! (client, _) = TestClient(config) |> initAndWaitForReply
use! client = TestClient(config) |> init

let responseRouterReturns = client.SendRequest("contextive/initialize")

Expand Down Expand Up @@ -59,7 +59,7 @@ let tests =
ConfigurationSection.contextivePathBuilder pathValue
showDocumentRequestHandlerBuilder <| handler showDocAwaiter showDocResponse ]

let! (client, _) = TestClient(config) |> initAndWaitForReply
use! client = TestClient(config) |> init

let responseRouterReturns = client.SendRequest("contextive/initialize")

Expand All @@ -70,7 +70,7 @@ let tests =

File.Delete(pathValue)

let! showDocMsg = ConditionAwaiter.waitForAny showDocAwaiter 5000
let! showDocMsg = ConditionAwaiter.waitForAny showDocAwaiter

test <@ showDocMsg.Value.Uri.ToString().Contains(pathValue) @>
}
Expand All @@ -90,7 +90,7 @@ let tests =

let existingContents = File.ReadAllText(fullPath)

let! (client, _) = TestClient(config) |> initAndWaitForReply
use! client = TestClient(config) |> init

let responseRouterReturns = client.SendRequest("contextive/initialize")

Expand All @@ -99,7 +99,7 @@ let tests =
|> Async.AwaitTask
|> Async.Ignore

let! showDocMsg = ConditionAwaiter.waitForAny showDocAwaiter 3000
let! showDocMsg = ConditionAwaiter.waitForAny showDocAwaiter

let newContents = File.ReadAllText(fullPath)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ let tests =
let! definitions = getDefinitionsWithErrorHandler onErrorLoading configGetter workspaceFolder
let! termsWhenInvalid = Definitions.find definitions "" id

let! errorMessage = ConditionAwaiter.waitForAny errorMessageAwaiter 500
let! errorMessage = ConditionAwaiter.waitForAny errorMessageAwaiter
test <@ errorMessage.Value = expectedErrorMessage @>
test <@ Seq.length termsWhenInvalid = 0 @>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type Message<'T> =
| WaitFor of WaitForCondition<'T>
| Clear

[<Literal>]
let private DEFAULT_TIMEOUT_MS = 5000

let create<'T> () =
let awaiter =
Expand Down Expand Up @@ -55,16 +57,29 @@ let create<'T> () =

let received (awaiter: MailboxProcessor<Message<'T>>) msg = awaiter.Post(Received(msg))

let waitFor (awaiter: MailboxProcessor<Message<'T>>) condition timeout =
/// Waits for a message that passes the condition to become true up to the nominated timeout.
let waitForTimeout timeoutMs (awaiter: MailboxProcessor<Message<'T>>) condition =
awaiter.PostAndTryAsyncReply(
(fun rc ->
WaitFor(
{ ReplyChannel = rc
Condition = condition }
)),
timeout
timeoutMs
)

let waitForAny (awaiter: MailboxProcessor<Message<'T>>) timeout = waitFor awaiter (fun _ -> true) timeout
/// Waits for a message that passes the condition to become true up to the default timeout of 5s.
/// If you want a custom timeout, use waitForTimeout.
let waitFor (awaiter: MailboxProcessor<Message<'T>>) =
waitForTimeout DEFAULT_TIMEOUT_MS awaiter

/// Waits for any message up to the nominated timeout.
let waitForAnyTimeout timeoutMs (awaiter: MailboxProcessor<Message<'T>>) =
waitForTimeout timeoutMs awaiter (fun _ -> true)

/// Waits for any message up to the default timeout of 5s.
/// If you want a custom timeout, use waitForAnyTimeout.
let waitForAny awaiter =
waitForAnyTimeout DEFAULT_TIMEOUT_MS awaiter

let clear (awaiter: MailboxProcessor<Message<'T>>) timeout = awaiter.Post(Clear)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let waitForLogMessage logAwaiter (logMessage: string) =
async {
let logCondition = fun (m: string) -> m.Contains(logMessage)

return! ConditionAwaiter.waitFor logAwaiter logCondition 25000
return! ConditionAwaiter.waitForTimeout 25000 logAwaiter logCondition
}

let optionsBuilder logAwaiter (b: LanguageClientOptions) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ type InitializationOptions =
type private TestClient() =
inherit LanguageServerTestBase(JsonRpcTestOptions())

override _.SetupServer() =
member _.AddToDisposable languageServer = base.Disposable.Add(languageServer)

override this.SetupServer() =
let clientPipe = Pipe()
let serverPipe = Pipe()

setupAndStartLanguageServer (serverPipe.Reader.AsStream()) (clientPipe.Writer.AsStream())
|> Async.Ignore
|> Async.Start
async {
let! server = setupAndStartLanguageServer (serverPipe.Reader.AsStream()) (clientPipe.Writer.AsStream())
// this.AddToDisposable server
()
}
|> Async.StartImmediate

(clientPipe.Reader.AsStream(), serverPipe.Writer.AsStream())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ let tests =
ConfigurationSection.contextivePathBuilder pathValue ]

let! (client, reply) = TestClient(config) |> initAndWaitForReply
use client = client

test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>

Expand All @@ -43,6 +44,7 @@ let tests =
let config = [ ConfigurationSection.contextivePathBuilder $"/tmp/{pathValue}" ]

let! (client, reply) = TestClient(config) |> initAndWaitForReply
use client = client

test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>

Expand All @@ -54,6 +56,7 @@ let tests =
let config = [ ConfigurationSection.contextivePathBuilder pathValue ]

let! (client, reply) = TestClientWithCustomInitWait(config, Some pathValue) |> initAndWaitForReply
use client = client

test <@ client.ClientSettings.Capabilities.Workspace.Configuration.IsSupported @>

Expand All @@ -72,6 +75,7 @@ let tests =
let defaultPath = ".contextive/definitions.yml"

let! (client, reply) = TestClient(config) |> initAndWaitForReply
use client = client

test <@ (defaultArg reply "").Contains(defaultPath) @>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ open Contextive.LanguageServer.Program
[<EntryPoint>]
let main argv =
setupLogging
VerifyTests.VerifierSettings.DisableRequireUniquePrefix()
runTestsInAssemblyWithCLIArgs [] argv
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ let tests =
ConfigurationSection.contextivePathBuilder $"one.yml"
WatchedFiles.optionsBuilder registrationAwaiter ]

let! client = TestClient(config) |> init
use! client = TestClient(config) |> init

let! registrationMsg = ConditionAwaiter.waitForAny registrationAwaiter 500
let! registrationMsg = ConditionAwaiter.waitForAny registrationAwaiter

test <@ client.ClientSettings.Capabilities.Workspace.DidChangeWatchedFiles.IsSupported @>

Expand All @@ -65,9 +65,9 @@ let tests =
ConfigurationSection.contextivePathLoaderBuilder pathLoader
WatchedFiles.optionsBuilder registrationAwaiter ]

let! client = TestClient(config) |> init
use! client = TestClient(config) |> init

let! initialRegistrationMsg = ConditionAwaiter.waitForAny registrationAwaiter 500
let! initialRegistrationMsg = ConditionAwaiter.waitForAny registrationAwaiter

ConditionAwaiter.clear registrationAwaiter 500

Expand All @@ -81,7 +81,6 @@ let tests =
match m with
| Registered(_) -> true
| _ -> false)
500

let! unregistrationMsg =
ConditionAwaiter.waitFor
Expand All @@ -90,7 +89,6 @@ let tests =
match m with
| Unregistered(_) -> true
| _ -> false)
500

match secondRegistrationMsg with
| Some(Registered(_, opts)) -> test <@ opts.Watchers |> watcherIsForFile newDefinitionsFile @>
Expand All @@ -115,7 +113,7 @@ let tests =
[ Workspace.optionsBuilder relativePath
ConfigurationSection.contextivePathBuilder definitionsFile ]

let! client = TestClient(config) |> init
use! client = TestClient(config) |> init

let definitionsFileUri =
Path.Combine(Directory.GetCurrentDirectory(), relativePath, definitionsFile)
Expand Down Expand Up @@ -153,7 +151,7 @@ let tests =
[ Workspace.optionsBuilder relativePath
ConfigurationSection.contextivePathBuilder definitionsFile ]

let! client = TestClient(config) |> init
use! client = TestClient(config) |> init

let definitionsFileUri =
Path.Combine(Directory.GetCurrentDirectory(), relativePath, definitionsFile)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,45 @@ contexts:
- name: CombinedWord
- name: octopus
- name: combined
- name: word
- name: word
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm
- name: newterm

0 comments on commit ee9aa75

Please sign in to comment.