Decomposability in Input Output Conformance Testing
We study the problem of deriving a specification for a third-party component, based on the specification of the system and the environment in which the component is supposed to reside. Particularly, we are interested in using component specifications for conformance testing of black-box components, using the theory of input-output conformance (ioco) testing. We propose and prove sufficient criteria for decompositionality, i.e., that components conforming to the derived specification will always compose to produce a correct system with respect to the system specification. We also study the criteria for strong decomposability, by which we can ensure that only those components conforming to the derived specification can lead to a correct system.
A. Petrenko, H. Schlingloff (Eds.): Eighth Workshop on Model-Based Testing (MBT 2013) EPTCS 111, 2013, pp. Decomposability in Input Output Conformance Testing–LABEL:LastPage, doi:10.4204/EPTCS.111.5
Decomposability in Input Output Conformance Testing
|Neda Noroozi \IfArrayPackageLoaded|
|email@example.com and Mohammad Reza Mousavi \IfArrayPackageLoaded|
|firstname.lastname@example.org and Tim A.C. Willemse \IfArrayPackageLoaded|
Enabling reuse and managing complexity are among the major benefits of using compositional approaches in software and systems engineering. This idea has been extensively adopted in several different subareas of software engineering, such as product-line software engineering. One of the cornerstones of the product-line approach is to reuse a common platform to build different products. This common platform should ideally comprise different types of artifacts, including test-cases, that can be re-used for various products of a given line. In this paper, we propose an approach to conformance testing, which allows to use a high-level specification and derive specifications for to-be-developed components (or sub-systems) given the platform on which they are to be deployed. We call this approach decompositional testing and refer to the process of deriving specifications as quotienting (inspired by its counterpart in the domain of formal verification).
We develop our approach within the context of input-output conformance testing (ioco) , a model-based testing theory using formal models based on input-output labeled transition systems (IOLTSs). An implementation is said to conform to a specification , denoted by , when after each trace in the specification, the outputs of the implementation are among those prescribed by the specifications.
For a given platform (environment) , whose behavior is given as an IOLTS, a quotient of a specification by the platform , denoted by , is the specification that describes the system after filtering out the effect of . The structure of a system consisting of and unknown component is represented in Figure 1, whose behavior is described by a given specification . We would like to construct such that it captures the behavior of any component which, when deployed on (put in parallel and possibly synchronize with ) conforms to . Put formally, is the specification which satisfies the following bi-implication:
The criteria for the implication from left to right, which is essential for our approach, are called decomposability. The criteria for the implication from right to left guarantee that quotienting produces the precise specification for the component and is called strong decomposability. We study both criteria in the remainder of this paper. Moreover, we show that strong decomposability can be combined with on-the-fly testing, thereby avoiding constructing the witness to the decomposability explicitly upfront.
The study of compositional and modular verification for various temporal and modal logics has attracted considerable attention and several compositional verification techniques have been proposed for such logics; see, e.g., [3, 8, 11, 7]. Decompositional reasoning aims at automatically decomposing the global property to be model checked into local properties of (possibly unknown) components, a technique that is often called quotienting. The notion of quotient introduced in the present paper is inspired by its corresponding notion in the area of (de)compositional model-checking, and is substantially adapted to the setting for input-output conformance testing, e.g., by catering for the distinction between input and output actions and taking care of (relative) quiescence of components. In the area of model-based testing, we are aware of a few studies dedicated to the issue of (de)composition [4, 6, 15], of which we give an overview below.
In  the compositionality of the ioco-based testing theory is investigated. Assuming that implementations of components conform to their specifications, the authors investigate whether the composition of these implementations still conforms to the composition of the specifications. They show that this is not necessarily the case and they establish conditions under which ioco is a compositional testing relation.
In , Frantzen and Tretmans study when successful integration of components by composing them in certain ways can be achieved. Successful integration is determined by two conditions: the integrated system correctly provides services, and interaction with other components is proper. For the former, a specification of the provided services of the component is assumed. Based on the ioco-relation, the authors introduce a new implementation relation called eco, which allows for checking whether a component conforms to its specification as well as whether it uses other components correctly. In addition, they also propose a bottom-up strategy for building an integrated systems.
Another problem closely related to the problem we consider in this paper is testing in context, also known as embedded testing . In this setting, the system under test comprises a component which is embedded in a context . Component is isolated from the environment and all its interactions proceed through (which is assumed to be correctly implemented). The implementation and specification of the system composed of and , are assumed to be available. The problem of testing in context then entails generating a test suite that allows for detecting incorrect implementations of component .
Although testing in context and decomposability share many characteristics, there are key differences between the two. We do not restrict ourselves to embedded components, nor do we assume the platforms to be fault-free. Contrary to the testing in context approach, decomposing a monolithic specification is the primary challenge in our work; testing in context already assumes the specification is the result of a composition of two specifications. Moreover, in testing in context, the component is tested through context whereas our approach allows for testing the component directly through its deduced specification. As a result, we do not require that the context is always available while testing the component, which is particularly important in case the platform is a costly resource.
We give a cursory overview of ioco-based formal testing in Section 2. The notions of decomposability and strong decomposability are formalized in Section 3. We present sufficient conditions for determining whether a given specification is decomposable in Section 4 and whether it is strongly decomposable in Section 5. We conclude in Section 6. Additional examples and results, together with all proofs for the lemmata and theorems can be found in .
Conformance testing is about checking that the observable behavior of the system under test is included in the prescribed behavior of the specification. In order to formally reason about conformance testing, we need a model for reasoning about the behaviors described by a specification, and assume that we have a formal model representing the behaviors of our implementations, so that we can reason about their conformance mathematically.
In this paper, we use variants of the well-known Labeled Transition Systems as a behavioral model for both the specification and the system under test. The Labeled Transition System model assumes that systems can be represented using a set of states and transitions, labeled with events or actions, between such states. A tester can observe the events leading to new states, but she cannot observe the states. We assume the presence of a special action , which we assume is unobservable to the tester.
Definition 1 (Iolts)
An input-output labeled transition system (IOLTS) is a tuple , where is a set of states, and are disjoint sets of observable inputs and outputs, respectively, is the transition relation (we assume ), and is the initial state. The class of IOLTSs ranging over inputs and outputs is denoted .
Throughout this section, we assume an arbitrary, fixed IOLTS , and we refer to this IOLTS by referring to its initial state . We write for the set . Let and . In line with common practice, we write rather than . Furthermore, we write whenever for some , and when not . A word is a sequence over the input and output symbols. The set of all words over is denoted , and is the empty word. For words , we denote the concatenation of and by . The transition relation is generalized to a relation over words by the following deduction rules:
We adopt the notational conventions we introduced for for . A state in the IOLTS is said to diverge if it is the source of an infinite sequence of -labeled transitions. The IOLTS is divergent if one of its reachable states diverges. Throughout this paper, we confine ourselves to non-divergent IOLTSs.
Let and . The set of traces, enabled actions and weakly enabled actions for and are defined as follows:
, and .
, and .
, and .
Quiescence and Suspension Traces.
Testers often not only have the power to observe events produced by an implementation, they can also observe the absence of events, or quiescence . A state is said to be quiescent if it does not produce outputs and it is stable. That is, it cannot, through internal computations, evolve to a state that is capable of producing outputs. Formally, state is quiescent, denoted , whenever . In order to formally reason about the observations of inputs, outputs and quiescence, we introduce the set of suspension traces. To this end, we first generalize the transition relation over words to a transition relation over suspension words. Let denote the set .
The following definition formalizes the set of suspension traces.
Let and . The set of suspension traces for , denoted is defined as the set ; we set .
Input-Output Conformance Testing with Quiescence.
Tretmans’ ioco testing theory  formalizes black box conformance of implementations. It assumes that the behavior of implementations can always be described adequately using a class of IOLTSs, called input output transition systems; this assumption is the so-called testing hypothesis. Input output transition systems are essentially plain IOLTSs with the additional assumption that inputs can always be accepted.
Definition 4 (Iots)
Let be an IOLTS. A state is input-enabled iff ; the IOLTS is an input output transition system (IOTS) iff every state is input-enabled. The class of input output transition systems ranging over inputs and outputs is denoted .
While the ioco testing theory assumes input-enabled implementations, it does not impose this requirement on specifications. This facilitates testing using partial specifications, i.e., specifications that are under-specified. We first introduce the main concepts that are used to define the family of conformance relations of the ioco testing theory.
Let be an IOLTS. Let , and let .
, and .
, and .
The family of conformance relations for ioco are then defined as follows, see also .
Definition 6 (ioco)
Let be an IOTS representing a realization of a system, and let IOLTS be a specification. Let . We say that is input output conform with specification , denoted , iff
The conformance relation can be specialized by choosing an appropriate set . For instance, in a setting with , we obtain the ioco relation originally defined by Tretmans in . The latter conformance relation is known to admit a sound and complete test case generation algorithm, see, e.g., [13, 14]. Soundness means, intuitively, that the algorithm will never generate a test case that, when executed on an implementation, leads to a fail verdict if the test runs are in accordance with the specification. Completeness is more esoteric: if the implementation has a behavior that is not in line with the specification, then there is a test case that, in theory, has the capacity to detect that non-conformance.
The original test case generation algorithm by Tretmans for the ioco relation relied on an automaton derived from an IOLTS specification. This automaton, called a suspension automaton, shares many of the characteristics of an IOLTS, except that the observations of quiescence are encoded explicitly as outputs: is treated as an ordinary action label which can appear on a transition. In addition, Tretmans assumes these suspension automata to be deterministic: any word that could be produced by an automaton leads to exactly one state in the automaton.
Definition 7 (Suspension automaton)
A suspension automaton(SA) is a deterministic ; that is, for all and all , we have .
Note that determinism implies the absence of transitions. In , a transformation from ordinary IOLTSs to suspension automata is presented; the transformation ensures that trace-based testing using the resulting suspension automaton is exactly as powerful as ioco-based testing using the original IOLTS.
The transformation is essentially based on the subset construction for determinizing automata. Given an IOLTS, the transformation defined below converts any IOLTS into an SA.
Let . The SA is defined as:
is the least relation satisfying:
Consider the IOLTS depicted in Figure 2 on page 2. The IOLTS is a specification of a malfunctioning vending machine which sells tea for one euro coin (c). After receiving money, it either delivers tea (t), refunds the money (r) or does nothing. Its suspension automaton , with initial state , is depicted next to it. Note that the suspension traces of and the traces of suspension automaton are identical.
In general, a suspension automaton may not represent an actual IOLTS; for instance, in an arbitrary suspension automaton, it is allowed to observe quiescence, followed by a proper output. This cannot happen in an IOLTS. In , the set of suspension automata is characterized for which a transformation to an IOLTS is possible. Such suspension automata are called valid. Proposition 1 of  states that for any IOLTS , the suspension automaton is valid. Conversely, Theorem 2 of  states that any valid suspension automaton has the same testing power (with respect to ioco) as some IOLTS. This essentially means that the class of valid suspension automata can be used safely for testing purposes.
A software or hardware system is usually composed of subunits and modules that work in an orchestrated fashion to achieve the desired overall behavior of the software or hardware system. In our setting, we can formalize such compositions using a special operator on IOLTSs: two IOLTSs can interact by connecting the outputs sent by one IOLTS to the inputs of the other IOLTS. We assume that such inputs and outputs are taken from a shared alphabet of actions. For the non-common actions the behavior of both IOLTSs is interleaved.
Definition 9 (parallel composition)
Let and be two IOLTSs with disjoint sets of input labels and , and disjoint sets of output labels and . The parallel composition of and , denoted is the IOLTS , where:
is the least relation satisfying:
The interaction between components is typically intended to be unobservable by a tester. This is not enforced by the parallel composition, but can be specified by combining parallel composition with a hiding operator, which is formalized below.
Definition 10 (hiding)
Let be an IOLTS, and let . The IOLTS resulting from hiding events from the set , denoted by is the IOLTS , where is defined as the least relation satisfying:
Note that the hiding operator may turn non-divergent IOLTSs into divergent IOLTSs. As divergence is excluded from the ioco testing theory, we must assume such divergences are not induced by composing two implementations in parallel and hiding all successful communications. Since implementations are assumed to be input enabled, this can only be ensured whenever components that are put in parallel never produce infinite, uninterrupted runs of outputs over their alphabet of shared output actions. Implementations adhering to these constraints are referred to as shared output bounded implementations. From hereon, we assume that all the implementions considered are shared output bounded.
Software can be constructed by decomposing a specification of the software in specifications of smaller complexity. Reuse of readily available and well-understood platforms or environments can steer such a decomposition. Given the prevalence of such platforms, the software engineering and associated testing problem thus shifts to finding a proper specification of the system from which the platform behavior has been factored out. Whether this is possible, however, depends on the specification; if so, we say that a specification is decomposable.
The decomposability problem requires known action alphabets for both the specification and the platform. Hence, we first fix these alphabets and illustrate how these are related. Hereafter, denotes the action alphabet of the specification and denotes the action alphabet of the platform . The actions of not exposed to are contained in action alphabet , i.e., we have . The action alphabet of the quotient will be denoted by , i.e. . The relation between the above alphabets is illustrated in Figure 1 in the introduction.
Definition 11 (Decomposability)
Let be a specification, and let be an implementation. Let be a set of actions of not part of . Specification is said to be decomposable for IOTS iff there is some specification for which both:
Decomposability of a specification essentially ensures that a specification for a subcomponent exists that guarantees that every ioco-correct implementation of it is also guaranteed to work correctly in combination with the platform.
Consider IOLTSs depicted in Figure 2. The IOTS 2(c) presents the behavioral model of an environment which after receiving a coin (c) either orders drink (order) or does nothing. Upon receiving an error signal (error), never refunds the money (r). Component interacts with another component through actions ‘order’ and ‘error’; together, the components implement a vending machine for which IOLTS 2(a) is the specification. The IOLTS 2(e) is a specification of a drink component which delivers tea after receiving a drink order. If it encounters a problem in delivering the drink, it signals an error. Specification guarantees that the combination of component with any drink component implementation conforming to , also conforms to .
It may, however, be the case that an implementation, in combination with a given platform, perfectly adheres to the overall specification , and, yet fails to pass the conformance test for . As a consequence, non-conformance of an implementation to may not by itself be a reason to reject the implementation.
Consider IOLTSs in Figure 2. The IOLTS 2(e) is a witness for decomposability of IOLTS 2(a) for platform 2(c). Thus, any compound system built of IOTS and a component conforming to is guaranteed to be in conformance with IOLTS . Now, consider IOTS 2(g) which incorrectly implements the functionality specified in IOLTS 2(e), as it sends ‘error’ twice. Observe that, nevertheless, still conforms to .
It is often desirable to consider specifications for which one only has to check whether an implementation adheres to , i.e., specifications for which it is guaranteed that a failure of an implementation to comply to also guarantees that the combination will violate the original specification . We can obtain this by considering a stronger notion of decomposability.
Definition 12 (Strong Decomposability)
Let be a specification, and let be an implementation. Let be a set of actions of not part of . Specification is said to be strongly decomposable for IOTS iff there is some specification for which both:
Consider the IOLTSs and in Figure 2; specification is such that the combination of component with any shared output bounded component that does not conform to , fails to comply to .
4 Sufficient Conditions for Decomposibility
Checking whether a given specification is decomposable is a difficult problem. However, knowing that a specification is decomposable in itself hardly helps a design engineer. Apart from the question whether a specification is decomposable, one is typically interested in a witness for the decomposed specification, or quotient. Our approach to the decomposability problem is therefore constructive: we define a quotient and we identify several conditions that ensure that the quotient we define is a witness for the decomposability of a given specification.
One of the problems that may prevent a specification from being decomposable for a given platform is that the latter may exhibit some behavior which unavoidably violates the specification . We shall therefore only consider platforms for which such violations are not present. We formalize this by checking whether the behavior of is included in the behavior of ; that is, we give conditions that ensure that in itself cannot violate the given specification . Moreover, we assume that the input-enabled specification of is available.
Assuming that the behavior of is included in the behavior of the given specification , we then propose a quotient of for and prove sufficient conditions that guarantee that is indeed decomposable and is a witness to that.
4.1 Inclusion relation
We say that the behavior of a given platform is included in a specification if the outputs allowed by subsume all outputs that can be produced by . For this, we need to take possible communications between and the to-be-derived quotient over the action alphabet into account. Another issue is that we are dealing with two components, each of which may be quiescent. If component is quiescent, its quiescence may be masked by outputs from the component with which it is supposed to interact. We must therefore consider a refined notion of quiescence. We say state in specification is relatively quiescent with respect to alphabet , denoted by , if produces no output of , i.e. . Analogous to , the suspension traces of can be enriched by adding the rule for to be able to formally reason about the possibility of being relatively quiescent with respect to . We write to denote this enriched set of suspension traces of .
Since the suspension traces of and differ as a result of different alphabets, we introduce a projection operator which allows us to map the suspension traces of to suspension traces of . The operator is defined as if ; , if ; otherwise, .
Let IOTS be an implementation. Let IOLTS be a specification. We say the behavior of is included in , denoted by iff
Consider the IOLTSs in Figure 2. We have . Consider the IOLTS which has the same functionality with IOLTS except that upon receiving an error signal (error), it may or may not refund the money (r). The behavior of is not included in , because of observing the output in after executing while after execution of reaches to a quiescent state.
We next focus on deriving a quotient of the specification , factoring out the behavior of the platform . A major source of complexity in defining such a quotient is the possible non-determinism that may be present in and . We largely avert this complexity by utilizing the suspension automata underlying and .
Another source of complexity is the fact that we must reason about the states of two systems running in parallel; such a system synchronizes on shared actions and interleaves on non-shared actions. We tame this conceptual complexity by formalizing an operator which, when executing a shared or non-shared action, keeps track of the set of reachable states for the (suspension automata) of and . Formally, the operator is defined as follows.
Let be a suspension automaton underlying specification IOLTS , and let be a suspension automaton underlying platform IOLTS . Let be a non-empty collection of sets and let .
Using the operator, we have an elegant construction of an automaton, called a quotient automaton, see below, which allows us to define sufficient conditions for establishing the decomposability of a given specification.
Definition 15 (Quotient Automaton)
Let be a suspension automaton underlying specification , and let be a suspension automaton underlying platform . The quotient of by , denoted by is a suspension automaton where:
, where ; for , we set and for , we set .
is the least set satisfying:
We briefly explain the construction of a quotient automaton. A non-shared input action is added to a state in the quotient automaton if an execution of the corresponding state in leads to a state in at which that action is enabled (, in combination with the second case in Definition 14). A shared input action obeys the same rule except that a state of has to be reachable where that input action is taken (, in combination with the first case in Definition 14). Note that a shared input action of is an output action from the viewpoint of . In contrast, a non-shared output action is allowed at a state of only if it is allowed by after any possible execution of () and a similar rule is applied to quiescence (). Analogous to the shared input actions, a shared output action is considered as an action of a state whenever a valid execution of the correspondent states in leads to a state at which that output action is enabled (). Because the shared actions are hidden in , a shared output action, in , may also be enabled at a state reached by transitions. Such a sequence of events is invalid due to the definition of quiescence. The observed problem is solved by adding a special set of states to the states of the quotient automaton. These states represent quiescent states corresponding to the reachable states after executing in . Moreover, no shared output action is added to these states.
The quotient automaton derived from specification and platform is a suspension automaton: it is deterministic and it has explicit labels. Yet, the quotient automata we derive are not necessarily valid suspension automata. (As we recalled in Section 2, only valid suspension automata have the same testing power as ordinary IOLTSs.) We furthermore observe that there some quotient automata that are valid suspension automata but nevertheless only admit non-shared output bounded implementations as implementations that conform to the quotient. As observed earlier, such implementations unavoidably give rise to divergent systems when composed in parallel with the platform.
Consider SAs depicted in Figure 3, IOLTSs and in Figure 2 and IOLTS derived by removing the internal transition from state to the initial state in . SA is the quotient of by . Likewise, SA is the quotient of by . Suspension automata and are valid SA regarding the definition of validity of suspension automata presented in  . Assume an arbitrary shared output bounded IOTS whose length of the longest sequence on the shared output is , i.e. . Clearly, , because . However, for any , there is always a shared output bounded IOTS that conforms to .
In view of the above, we say that a quotient automaton is valid if it is a valid suspension automaton and strongly non-blocking.
Let be a quotient automaton derived from a specification and an environment . We say that is valid iff both:
is a valid suspension automaton, and
is strongly non-blocking, i.e. .
Strongly non-blocking ensures that the quotient automaton always admits a shared output bounded implementation that conforms to it. Furthermore, valid quotient automata are, by definition, also valid suspension automata. Since every valid suspension automaton underlies at least one IOLTS, we therefore have established a sufficient condition for the decomposability of a specification.
Let be a specification and let be an environment. Then is decomposable for if is a valid quotient automaton and .
Note that the IOLTS underlying the quotient automaton is a witness to the decomposability of the specification; we thus not only have a sufficient condition for the decomposability of a specification but also a witness for the decomposition.
To illustrate the notions introduced so far, we treat a simplified model of an Electronic Funds Transfer (EFT) switch, which we have studied and tested using ioco-based techniques . A schematic view of this example is depicted in Figure 4(a). An EFT switch provides a communication mechanism among different components of a card-based financial system. On one side of the EFT switch, there are components, with which the end-user deals, such as Automated Teller Machines (ATMs), Point-of-Sale (POS) devices and e-Payment applications. On the other side, there are banking systems and the inter-bank network connecting the switches of different financial institutions.
The various involving parties in every transaction performed by an EFT switch in conjunction with the variety of financial transactions complicate the behavioral model of the EFT switch. Similar to any other complex software system, the EFT switch comprises many different components, some of which can be run individually.
A part of the simplified communication model of the EFT switch with a banking system in the purchase scenario is depicted in Figure 4(b). The scenario starts by receiving a purchase request from a POS; this initial part of the scenario is removed from the model, for the sake of brevity. Subsequently, the EFT switch sends a purchase request () to the banking system. The EFT switch will reverse () the sent purchase request if the corresponding response () is not received within a certain amount of time (e.g, an internal time-out occurs, denoted by ). Due to possible delays in the network layer of the EFT switch, an external observer (tester) may observe the reverse request of a purchase even before the purchase request which is pictured in Fig 4(b).
The EFT switch is further implemented in terms of two components, namely, the financial component and the reversal component. A simplified behavioral model of the financial component is given in Figure 4(c). Comparing the two languages of and , action (representing time-out) is considered as an internal interface between and a to-be-developed implementation of the reversal component. Observe that for every sequence in , it holds that ; thus, the behavior of is included in . We next instigate investigate decomposability of with , by constructing the quotient . Note that is the only shared action which is an input action from the view point of . The resulting quotient automaton, obtained by applying Definition 15 to and is depicted in Figure 4(d). We illustrate some steps in its derivation. The initial state of the quotient automaton is defined as the . Below, we illustrate which of the rules of Definition 15 are possible from this initial state; doing so repeatedly for all reached states will ultimately produce the reachable states of the quotient automaton.
We check the possibility of adding output transitions to . We observe that for every . Regarding deduction rule , the transition is added to the transition relation of where (state 2 in Figure 4(d)).
Following deduction rule and , -labeled transition is not added to .
The constructed quotient automaton is valid: it is both a valid suspension automaton and strongly non-blocking. As a result, is decomposable with respect to and is a witness to that.
5 Strong Decomposibility
It is a natural question whether the quotient automaton that we defined in the previous section, along with the sufficient conditions for decomposability of a specification provide sufficient conditions for strong decomposability. The proof of Theorem 1 gives some clues to the contrary. A main problem is in the notion of quiescence, and, in particular in the notion of relative quiescence, which is unobservable in the standard ioco theory. More specifically, the platform may mask the (unwanted) lack of outputs of the quotient automaton.
A natural solution to this is to consider a subclass of implementations called internal choice IOTSs, studied in [9, 16]: such implementations only accept inputs when reaching a quiescent state. The proposition below states that strong decomposability can be achieved under these conditions.
Let be a specification and let be an environment. If is decomposable and is an internal choice IOTS then is strongly decomposable and is a witness to this.
As a result of the above theorem, testing whether the composition of a component and a platform conforms to specification reduces to testing for the conformance of to . This can be done using the standard ioco testing theory .
A problem may arise when trying this approach in practice. Namely, the amount of time and memory needed for derivation of the ioco test suit increases exponentially in the number of transitions in the specification due to the nondeterministic nature of the test-case generation algorithm. We avoid these complexities by presenting an on-the-fly testing algorithm inspired by . Algorithm 1 describes the on-the-fly testing algorithm in which sound test cases are generated without constructing the quotient automaton upfront. We partially explored the quotient automaton during test execution. We use the extended version of operator in Algorithm 1 which is defined on ordinary IOLTSs; the underlying IOLTSs of suspension automata is used to avoid the complexity of constructing suspension automata, i.e. .
Let be a specification and let be an environment. Let be an implementation tested against