Replies: 3 comments 1 reply
-
Additional question. Task notifications have an optional |
Beta Was this translation helpful? Give feedback.
-
Thanks @agluszak for this comprehensive discussion of the BSP test workflow. [1] I am more in favor of the second option: the
To be flexible we should allow a build target to contain many test groups. But also to keep things simple we should only require a single test report on each build target. We can also have a optional test report on a test group (but I don't think we need one). I don't like the Maybe the [2] It would make sense to report progress of a test group given that we know the total number of tests. But do we have any client that need that? [3]
LGTM [4] Looks like a detail to me. We can remove the field or we can specify that it should be the same as in the [5]
This is how I understand it:
[6] Similarly this status should be success except if something unexpected happened such as the crash of the runner. [7] Same comment as [4] [8] The server is always right. But the client is free to ignore the report if it feels like it should re-compute it. [10]
I totally agree, the reset mechanism is not easy to implement at the server side. The [11] This problem is a recurring one. It is also described in #655 and I proposed a solution in #204. The multi-target request is at the core of BSP and we should have a multi-target response to handle success and failures at the target level. |
Beta Was this translation helpful? Give feedback.
-
Since there is already a parent-child structure, is there a need for |
Beta Was this translation helpful? Give feedback.
-
A simple task of requesting the server to run some tests turns out to hit a lot of undefined or vaguely defined areas in the protocol specification. Let's review a few scenarios and encode the conclusions in the spec.
Scenario 1 (the simplest happy case):
User wants to test target T1 which contains only one test case C1. There is no compilation involved. C1 succeeds.
In my opinion, the json-rpc exchange between the client and the server should look like this:
buildTarget/test
(client -> server)build/taskStart
(server -> client) [1]build/taskStart
(server -> client) [2]build/taskFinish
(server -> client)build/taskFinish
(server -> client)buildTarget/test
(request response, server -> client)Scenario 2 (the simplest failure case)
User wants to test target T1 which contains only one test case C1. There is no compilation involved. C1 fails.
My understanding is that exactly the same as above would happen, but with different statuses. Certainly the TestStatus should be set to 2, but what about the rest? I'd say that all of them should be set to 1 (OK), because both the TestTask and the test request itself succeeded. TestFinish task itself also succeeded, even though the test failed. But if so, what would it mean if the task failed? There's nothing about this in the spec currently.
Scenario 3 (multiple test cases)
User wants to test target T1 which contains two test cases C1 and C2. There is no compilation involved. C1 succeeds, C2 fails.
There is one "outer"
TestTask
task. So there would be 3build/taskStart
notifications and 3 matchingbuild/taskFinish
notifications.Scenario 4 (multiple targets)
User wants to test targets T1 and T2 in one request. T1 contains two test cases C1 and C2. T2 contains test case C3. No compilation.
My understanding is that there would be 5
build/taskStart
notifications.Unless we agree that there has to be an additional top level task.
Scenario 5 (building)
User wants to test target T1 which contains only one test case C1. T1 needs to be built first.
My understanding is that there would be 3 task
build/taskStart
notifications.Before notifications described in Scenario 1 there would be a
CompileTask
notification, perhaps followed by somebuild/taskProgress
notifications.Scenario 6 (cancellation)
Same as above, but the user cancels the task before the target is built or before the tests are run.
statusCode
inTestResult
(result of the entire request) is set to 3 (cancelled)[12]. If the cancellation happens before the tests are run, but after the building is done - task notifications from building are sent from the server to the client.Scenario 7 (building error)
Same as above, but building/compilation fails.
buildTarget/test
(client -> server)build/taskStart
(server -> client)build/taskProgress
(server -> client)build/publishDiagnostics
(server -> client)build/taskFinish
(server -> client)buildTarget/test
(request response, server -> client)[1] In my opinion we need to say in the spec either that:
TestReport
task notification later on. However this significantly increases the implementation complexity, because now there are two code paths: either all tests are grouped under a top level task or they are parentless. This essentially makes theTestReport
task notification useless, because a compliant BSP client would always have to be able to handle both cases: withTestReport
(so it doesn't have to keep track of the number of succeeded/failed/ignored test) or without one. In other words: depending on whether you get aTestReport
the test statistics have to be computed either on the client side or on the server side.TestReport
must be sent after all tests for a given target are run. This, however, makes the task mechanism useless for this usecase, because this data could be included in theTestResult
response (which is, by definition, always returned for abuildTarget/test
request).The spec currently says here that "The beginning of a testing unit may be signalled to the client with a build/taskStart notification. When the testing unit is a build target, the notification's dataKind field must be test-task and the data field must include a TestTask object."
What else can be a testing unit? What if you have multiple "testing units" in a build target? Will you get multiple
TestReport
s? Or should there be a top level task anyway? (with its ownTestReport
?). I feel like this part of the specification tries to be too general.[2] Should we also send a
build/taskProgress
[13] notification? Or instead of this one? Technically speaking, running a test case is a form of making progress in the greater task of testing a build target. The spec even suggests thatbuild/taskProgress
notification can be used for telling the client about running tests:However, in my opinion, it makes no sense to use
build/taskProgress
for reporting of tests being started, because that prevents you from getting aTestFinish
notification later on. So we should explicitly prohibit that.[3] In theory, once a task has started, the list of parents can no longer change. So this field could be ignored. But what if it's present and, what's worse, it contains data different from what it contained when the task was started? We could say in the specification that for notifications other than
build/taskStarted
this field MUST be absent. But then havingTaskId
as a separate structure would no longer make sense and it would be simpler to "extract" its fields directly to the fields of the notification parameters.build/taskStart
would have bothid
andparents
,build/taskProgress
andbuild/taskFinish
would only haveid
.[4] What should happen in the client if it’s different from the name received in the start notification? What is the point of the possibility that these two values could be different? Also: why is this field present in test notifications, but not compile notifications?
IMO we need to clarify that this field SHOULD NOT be used as an identifier.
[5] How is one status different from another? How can a test succeed, but the task containing it fail?
[6] What does this status really mean? Should it be set to failed if any of the contained tests fail? Or should it be always set to OK and ignored?
[7] Redundant. We already know that form the
TestTask
notification.[8] As mentioned in [1], what if this number is not equal to the number of
TestFinish
notifications withstatus == 1
received? Who should be the authority computing the stats? The client or the server?[9] This time the meaning of this yet another status is clear, as it is the status of the entire request. It will be discussed later on.
[10] Perhaps instead of this boolean switch (which, from my experience as an implementor, is hard to work with, because it requires some implicit, mutable state) we could have an obligatory
taskId
field. This way we would always know which diagnostics should be displayed together, even if they come in separate batches. If you use BSP for, for example, background typechecking - then each time the compiler runs and starts spawning diagnostics - start a new task.[11] That's a failure, because we didn't even get to the testing part, I guess? But what if there are multiple targets and they can be built and tested independently, in parallel? What if, let's say, one target builds fine and is tested successfully, but another one breaks in the process of testing?
[12] Oh, now I remember that we already talked about cancellation and it turned out that our cancelled status code only exist because the original authors of the BSP spec weren't aware of the LSP cancellation mechanism or it didn't exist back then.
[13] Regarding progress notifications: just a reminder that the LSP base protocol (on which we'd probably like to rebase BSP in version 3.0) contains a progress reporting mechanism
Beta Was this translation helpful? Give feedback.
All reactions