| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /// The dynamic suite is a mechanism to test dynamic properties of FIDL bindings |
| /// in a uniform way. This makes it possible to express various behaviors that |
| /// bindings should adhere to, and then ensure that all bindings conform to that |
| /// behavior. |
| /// |
| /// The anatomy of the dynamic suite is a generic harness, written once for all |
| /// bindings. Individual tests are written in the harness. This harness then |
| /// interacts with one specific binding under test. By assembling the harness |
| /// and a different binding to interact with in a component, we can ensure that |
| /// all bindings are exercised in the same way. |
| /// |
| /// Bindings under test implement the `ServerTest` protocol when server |
| /// implementation is exercised, and the `ClientTest` prtocool when client |
| /// implementation is exercised. Bindings under test must record observations |
| /// of their internal state by invoking the `Observer.Observe` method. |
| /// |
| /// As a result, the harness can interact freely with a binding, and check |
| /// various boundary conditions knowing the binding under test will send |
| /// specific observations, against which the harness will then be able to make |
| /// assertions. |
| /// |
| /// For instance, the harness may send an invalid message to the bindings under |
| /// test only to expect those bindings to error, and close the channel. Should |
| /// the bindings under test fail to behave as expected, the harness is able to |
| /// fail the test (due to missed expecations). |
| library fidl.dynsuite; |
| |
| using zx; |
| |
| @discoverable |
| protocol Entry { |
| StartServerTest(resource struct { |
| server_end server_end:ServerTest; |
| observer client_end:Observer; |
| }); |
| StartClientTest(resource struct { |
| client_end client_end:ClientTest; |
| observer client_end:Observer; |
| }); |
| }; |
| |
| /// Base defines all interactions used to test servers and clients, and is |
| /// composed into `ServerTest` and `ClientTest`. |
| protocol Base { |
| OneWayInteractionNoPayload(); |
| }; |
| |
| /// ServerTest defines a protocol which the server under test should implement. |
| /// Once the server under test is bound, the harness will interact with the |
| /// server in various ways (sometimes, erroneously) to verify boundary |
| /// conditions. As an example, the harness may send an unknown ordinal, or an |
| /// incorrect payload. |
| protocol ServerTest { |
| compose Base; |
| }; |
| |
| /// ClientTest defines a protocol which the client under test should interact |
| /// with in order to test various boundary conditions. The harness will |
| /// implement the server, and respond to the client in various ways (sometimes, |
| /// erroneously). As an example, the harness may fail to respond at all, or |
| /// respond with an incorrect payload. |
| protocol ClientTest { |
| // TODO(fxbug.dev/88343): Use top-level union directly. |
| -> OnPleaseDo(struct { |
| action ClientAction; |
| }); |
| |
| compose Base; |
| }; |
| |
| type ClientAction = strict union { |
| 1: close_channel struct {}; |
| 2: invoke Method; |
| }; |
| |
| /// The Method lists all methods for which observations must be reported by the |
| /// bindings under test. |
| type Method = strict enum { |
| /// For [`Base.OneWayInteractionNoPayload`]. |
| ONE_WAY_INTERACTION_NO_PAYLOAD = 2; |
| }; |
| |
| /// The MethodPoint enum identifies the entry of a method, or the exit of a |
| /// method. |
| type MethodPoint = strict enum { |
| ENTER = 1; |
| EXIT = 2; |
| }; |
| |
| /// The Observation union describes the various observations which the bindings |
| /// under test can send to the harness. These observations describe various |
| /// states reached by the bindings under test. |
| type Observation = strict union { |
| /// The [`on_bind`] variant is always observed first, and indicates that the |
| /// bindings under test have started listening for messages on the endpoint |
| /// provided by the harness (i.e. either through [`Entry.StartServerTest`] |
| /// or [`Entry.StartClientTest`]). |
| 1: on_bind struct {}; |
| |
| /// The [`on_method_invocation`] variant indicates that a method was |
| /// invoked on the bindings under test. Both entry and exit of the invoked |
| /// method is reported. |
| 2: on_method_invocation struct { |
| method Method; |
| method_point MethodPoint; |
| }; |
| |
| /// The [`on_unbind`] variant indicates that the bindings under test have |
| /// stopped listening for messages. This could be expected, or abnormal. |
| /// See also the [`on_error`] variant. |
| 3: on_unbind struct {}; |
| |
| /// The [`on_complete`] variant indicates that the currently running test |
| /// has completed from the perspective of the bindings under test. This |
| /// observation should follow the [`on_unbind`] observation, though some |
| /// bindings under may instrument both differently providing more details |
| /// to the harness of the destruction sequence. |
| 4: on_complete struct {}; |
| |
| /// The [`on_error`] variant indicates that some error occurred in the |
| /// bindings under test. The `context` string is depedendant on the kind |
| /// of bindings being tested, and is provided for informational purposes. |
| 5: on_error struct { |
| context string; |
| err zx.status; |
| }; |
| }; |
| |
| /// Observer protocols allows the bindings under test to report state changes |
| /// and other interesting observations to the test harness. |
| protocol Observer { |
| /// Sends an observation to the test harness. |
| // TODO(fxbug.dev/88343): Use top-level union directly. |
| Observe(struct { |
| observation Observation; |
| }); |
| }; |