Sophie

Sophie

distrib > Mageia > 7 > x86_64 > by-pkgid > ad5d2ef91c7983b02b7da4ed2a0e776f > files > 48

erlang-proper-1.3-2.mga7.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Module proper_statem</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
</head>
<body bgcolor="white">
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
<hr>

<h1>Module proper_statem</h1>
<ul class="index"><li><a href="#description">Description</a></li><li><a href="#types">Data Types</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>This module defines the <code>proper_statem</code> behaviour, useful for testing
   stateful reactive systems whose internal state and side-effects are
   specified via an abstract state machine.
<p>Copyright © 2010-2018 Manolis Papadakis, Eirini Arvaniti and Kostis Sagonas</p>

<p><b>Version:</b> Sep 22 2018 19:52:29</p>
<p><b>Authors:</b> Eirini Arvaniti.</p>

<h2><a name="description">Description</a></h2><p>This module defines the <code>proper_statem</code> behaviour, useful for testing
   stateful reactive systems whose internal state and side-effects are
   specified via an abstract state machine. Given a callback module
   implementing the <code>proper_statem</code> behaviour (i.e. defining an abstract state   
machine of the system under test), PropEr can generate random symbolic   
sequences of calls to that system.   
As a next step, generated symbolic calls are actually performed, while   
monitoring the system's responses to ensure it behaves as expected. Upon   
failure, the shrinking mechanism attempts to find a minimal sequence of   
calls provoking the same error.</p>
  
   <p>When including the <code>"proper/include/proper.hrl"</code> header file,
   all <a href="#index">API functions </a> of proper_statem are automatically
   imported, unless <code>PROPER_NO_IMPORTS</code> is defined.</p>
  
   <h4><a name="The_role_of_commands">The role of commands</a></h4>
   Testcases generated for testing a stateful system are lists of symbolic API
   calls to that system. Symbolic representation has several benefits, which
   are listed here in increasing order of importance:
   <ul>
   <li>Generated testcases are easier to read and understand.</li>
   <li>Failing testcases are easier to shrink.</li>
   <li>The generation phase is side-effect free and this results in
     repeatable testcases, which is essential for correct shrinking.</li>
   </ul><p>
   Since the actual results of symbolic calls are not known at generation time,
   we use symbolic variables (<code><a href="#type-symbolic_var">symbolic_var()</a></code>) to refer to them.
   A command (<code><a href="#type-command">command()</a></code>) is a symbolic term, used to bind a symbolic   
variable to the result of a symbolic call. For example:</p>
  
   <pre>      [{set, {var,1}, {call,erlang,put,[a,42]}},
       {set, {var,2}, {call,erlang,erase,[a]}},
       {set, {var,3}, {call,erlang,put,[b,{var,2}]}}]</pre>
  
   <p>is a command sequence that could be used to test the process dictionary.
   In this example, the first call stores the pair <code>{a,42}</code> in the process
   dictionary, while the second one deletes it. Then, a new pair <code>{b,{var,2}}</code>
   is stored. <code>{var,2}</code> is a symbolic variable bound to the result of
   <code>erlang:erase/1</code>. This result is not known at generation time, since none of
   these operations is performed at that time. After evaluating the command
   sequence at runtime, the process dictionary will eventually contain the
   pair <code>{b,42}</code>.</p>
  
   <h4><a name="The_abstract_model-state">The abstract model-state</a></h4>
   In order to be able to test impure code, we need a way to track its
   internal state (at least the useful part of it). To this end, we use an
   abstract state machine representing the possible configurations of the
   system under test. When referring to the <i>model state</i>, we mean the
   state of the abstract state machine. The <i>model state</i> can be either
   symbolic or dynamic:
   <ul>
   <li>During command generation, we use symbolic variables to bind the
   results of symbolic calls. Therefore, the model state might
   (and usually does) contain symbolic variables and/or symbolic calls, which
   are necessary to operate on symbolic variables. Thus, we refer to it as
   symbolic state. For example, assuming that the internal state of the
   process dictionary is modeled as a proplist, the model state after
   generating the previous command sequence will be <code>[{b,{var,2}}]</code>.</li>
   <li>During runtime, symbolic calls are evaluated and symbolic variables are
   replaced by their corresponding real values. Now we refer to the state as
   dynamic state. After running the previous command sequence, the model state
   will be <code>[{b,42}]</code>.</li>
   </ul>
  
   <h4><a name="The_callback_functions">The callback functions</a></h4>
   The following functions must be exported from the callback module
   implementing the abstract state machine:
   <ul>
   <li><code>initial_state() -&gt;</code> <code><a href="#type-symbolic_state">symbolic_state()</a></code>
     <p>Specifies the symbolic initial state of the state machine. This state
     will be evaluated at command execution time to produce the actual initial
     state. The function is not only called at command generation time, but
     also in order to initialize the state every time the command sequence is
     run (i.e. during normal execution, while shrinking and when checking a
     counterexample). For this reason, it should be deterministic and
     self-contained.</p></li>
   <li><code>command(S::</code><code><a href="#type-symbolic_state">symbolic_state()</a></code><code>) -&gt;</code> <code><a href="proper_types.html#type-type">proper_types:type()</a></code>
     <p>Generates a symbolic call to be included in the command sequence,
     given the current state <code>S</code> of the abstract state machine. However,
     before the call is actually included, a precondition is checked. This
     function will be repeatedly called to produce the next call to be
     included in the test case.</p></li>
   <li><code>precondition(S::</code><code><a href="#type-symbolic_state">symbolic_state()</a></code><code>,
                     Call::</code><code><a href="#type-symbolic_call">symbolic_call()</a></code><code>) -&gt; boolean()</code>
     <p>Specifies the precondition that should hold so that <code>Call</code> can be
     included in the command sequence, given the current state <code>S</code> of the
     abstract state machine. In case precondition doesn't hold, a new call is
     chosen using the <code>command/1</code> generator. If preconditions are very strict,
     it will take a lot of tries for PropEr to randomly choose a valid command.
     Testing will be stopped in case the <code>constraint_tries</code> limit is reached
     (see the 'Options' section in the <a href="proper.html"><code>proper</code></a> module documentation).
     Preconditions are also important for correct shrinking of failing
     testcases. When shrinking command sequences, we try to eliminate commands
     that do not contribute to failure, ensuring that all preconditions still
     hold. Validating preconditions is necessary because during shrinking we
     usually attempt to perform a call with the system being in a state
     different from the state it was when initially running the test.</p></li>
   <li><code>postcondition(S::</code><code><a href="#type-dynamic_state">dynamic_state()</a></code><code>,
                      Call::</code><code><a href="#type-symbolic_call">symbolic_call()</a></code><code>,
                      Res::term()) -&gt; boolean()</code>
     <p>Specifies the postcondition that should hold about the result <code>Res</code> of
     performing <code>Call</code>, given the dynamic state <code>S</code> of the abstract state
     machine prior to command execution. This function is called during
     runtime, this is why the state is dynamic.</p></li>
   <li><code>next_state(S::</code><code><a href="#type-symbolic_state">symbolic_state()</a></code> <code>|</code> <code><a href="#type-dynamic_state">dynamic_state()</a></code><code>,
                   Res::term(),
                   Call::</code><code><a href="#type-symbolic_call">symbolic_call()</a></code><code>) -&gt;</code>
          <code><a href="#type-symbolic_state">symbolic_state()</a></code> <code>|</code> <code><a href="#type-dynamic_state">dynamic_state()</a></code>
     <p>Specifies the next state of the abstract state machine, given the
     current state <code>S</code>, the symbolic <code>Call</code> chosen and its result <code>Res</code>. This
     function is called both at command generation and command execution time
     in order to update the model state, therefore the state <code>S</code> and the
     result <code>Res</code> can be either symbolic or dynamic.</p></li>
   </ul>
  
   <h4><a name="The_property_used">The property used</a></h4>
   Each test consists of two phases:
   <ul>
   <li>As a first step, PropEr generates random symbolic command sequences
     deriving information from the callback module implementing the abstract
     state machine. This is the role of <a href="#commands-1"><code>commands/1</code></a> generator.</li>
   <li>As a second step, command sequences are executed so as to check that
     the system behaves as expected. This is the role of
     <a href="#run_commands-2"><code>run_commands/2</code></a>, a function that evaluates a symbolic command
     sequence according to an abstract state machine specification.</li>
   </ul>
  
   <p>These two phases are encapsulated in the following property, which can be   
used for testing the process dictionary:</p>
  
   <pre>      prop_pdict() -&gt;
          ?FORALL(Cmds, proper_statem:commands(?MODULE),
                  begin
                      {_History, _State, Result} = proper_statem:run_commands(?MODULE, Cmds),
                      cleanup(),
                      Result =:= ok
                  end).</pre>
  
   <p>When testing impure code, it is very important to keep each test   
self-contained. For this reason, almost every property for testing stateful   
systems contains some clean-up code. Such code is necessary to put the   
system in a known state, so that the next test can be executed   
independently from previous ones.</p>
  
   <h3><a name="Parallel_testing">Parallel testing</a></h3><p>
   After ensuring that a system's behaviour can be described via an abstract
   state machine when commands are executed sequentially, it is possible to
   move to parallel testing. The same state machine can be used to generate
   command sequences that will be executed in parallel to test for race
   conditions. A parallel testcase (<code><a href="#type-parallel_testcase">parallel_testcase()</a></code>) consists of   
a sequential and a parallel component. The sequential component is a   
command sequence that is run first to put the system in a random state.   
The parallel component is a list containing 2 command sequences to be   
executed in parallel, each of them in a separate newly-spawned process.</p>
  
   <p>Generating parallel test cases involves the following actions. Initially,
   we generate a command sequence deriving information from the abstract
   state machine specification, as in the case of sequential statem testing.
   Then, we parallelize a random suffix (up to 12 commands) of the initial
   sequence by splitting it into 2 subsequences that will be executed
   concurrently. Limitations arise from the fact that each subsequence should
   be a <i>valid</i> command sequence (i.e. all commands should satisfy
   preconditions and use only symbolic variables bound to the results of
   preceding calls in the same sequence). Furthermore, we apply an additional
   check: we have to ensure that preconditions are satisfied in all possible
   interleavings of the concurrent tasks. Otherwise, an exception might be
   raised during parallel execution and lead to unexpected (and unwanted) test
   failure. In case these constraints cannot be satisfied for a specific test
   case, the test case will be executed sequentially. Then an <code>f</code> is printed   
on screen to inform the user. This usually means that preconditions need   
to become less strict for parallel testing to work.</p>
  
   <p>After running a parallel testcase, PropEr uses the state machine   
specification to check if the results observed could have been produced by   
a possible serialization of the parallel component. If no such serialization   
is possible, then an atomicity violation has been detected. In this case,   
the shrinking mechanism attempts to produce a counterexample that is minimal   
in terms of concurrent operations. Properties for parallel testing are very   
similar to those used for sequential testing.</p>
  
   <pre>      prop_parallel_testing() -&gt;
          ?FORALL(Testcase, proper_statem:parallel_commands(?MODULE),
                  begin
                      {_Sequential, _Parallel, Result} = proper_statem:run_parallel_commands(?MODULE, Testcase),
                      cleanup(),
                      Result =:= ok
                  end).</pre>
  
   Please note that the actual interleaving of commands of the parallel
   component depends on the Erlang scheduler, which is too deterministic.
   For PropEr to be able to detect race conditions, the code of the system
   under test should be instrumented with <code>erlang:yield/0</code> calls to the
   scheduler.
<h2><a name="types">Data Types</a></h2>

<h3 class="typedecl"><a name="type-command">command()</a></h3>
<p><pre>command() = 
    {set, <a href="#type-symbolic_var">symbolic_var()</a>, <a href="#type-symbolic_call">symbolic_call()</a>} |
    {init, <a href="#type-symbolic_state">symbolic_state()</a>}</pre></p>


<h3 class="typedecl"><a name="type-command_list">command_list()</a></h3>
<p><pre>command_list() = [<a href="#type-command">command()</a>]</pre></p>


<h3 class="typedecl"><a name="type-dynamic_state">dynamic_state()</a></h3>
<p><b>abstract datatype</b>: <tt>dynamic_state()</tt></p>


<h3 class="typedecl"><a name="type-history">history()</a></h3>
<p><pre>history() = [{<a href="#type-dynamic_state">dynamic_state()</a>, term()}]</pre></p>


<h3 class="typedecl"><a name="type-mod_name">mod_name()</a></h3>
<p><pre>mod_name() = atom()</pre></p>


<h3 class="typedecl"><a name="type-parallel_history">parallel_history()</a></h3>
<p><pre>parallel_history() = [{<a href="#type-command">command()</a>, term()}]</pre></p>


<h3 class="typedecl"><a name="type-parallel_testcase">parallel_testcase()</a></h3>
<p><pre>parallel_testcase() = {<a href="#type-command_list">command_list()</a>, [<a href="#type-command_list">command_list()</a>]}</pre></p>


<h3 class="typedecl"><a name="type-statem_result">statem_result()</a></h3>
<p><pre>statem_result() = 
    ok |
    initialization_error |
    {precondition, false | <a href="proper.html#type-exception">proper:exception()</a>} |
    {postcondition, false | <a href="proper.html#type-exception">proper:exception()</a>} |
    <a href="proper.html#type-exception">proper:exception()</a> |
    no_possible_interleaving</pre></p>


<h3 class="typedecl"><a name="type-symbolic_call">symbolic_call()</a></h3>
<p><b>abstract datatype</b>: <tt>symbolic_call()</tt></p>


<h3 class="typedecl"><a name="type-symbolic_state">symbolic_state()</a></h3>
<p><b>abstract datatype</b>: <tt>symbolic_state()</tt></p>


<h3 class="typedecl"><a name="type-symbolic_var">symbolic_var()</a></h3>
<p><pre>symbolic_var() = {var, pos_integer()}</pre></p>


<h2><a name="index">Function Index</a></h2>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#command_names-1">command_names/1</a></td><td>Extracts the names of the commands from a given command sequence, in
  the form of MFAs.</td></tr>
<tr><td valign="top"><a href="#commands-1">commands/1</a></td><td>A special PropEr type which generates random command sequences,
  according to an abstract state machine specification.</td></tr>
<tr><td valign="top"><a href="#commands-2">commands/2</a></td><td>Similar to <a href="#commands-1"><code>commands/1</code></a>, but generated command sequences always
  start at a given state.</td></tr>
<tr><td valign="top"><a href="#more_commands-2">more_commands/2</a></td><td>Increases the expected length of command sequences generated from
  <code>CmdType</code> by a factor <code>N</code>.</td></tr>
<tr><td valign="top"><a href="#parallel_commands-1">parallel_commands/1</a></td><td>A special PropEr type which generates parallel testcases,
  according to an absract state machine specification.</td></tr>
<tr><td valign="top"><a href="#parallel_commands-2">parallel_commands/2</a></td><td>Similar to <a href="#parallel_commands-1"><code>parallel_commands/1</code></a>, but generated command sequences
  always start at a given state.</td></tr>
<tr><td valign="top"><a href="#run_commands-2">run_commands/2</a></td><td>Evaluates a given symbolic command sequence <code>Cmds</code> according to the
   state machine specified in <code>Mod</code>.</td></tr>
<tr><td valign="top"><a href="#run_commands-3">run_commands/3</a></td><td> Similar to <a href="#run_commands-2"><code>run_commands/2</code></a>, but also accepts an environment,
  used for symbolic variable evaluation during command execution.</td></tr>
<tr><td valign="top"><a href="#run_parallel_commands-2">run_parallel_commands/2</a></td><td>Runs a given parallel testcase according to the state machine
  specified in <code>Mod</code>.</td></tr>
<tr><td valign="top"><a href="#run_parallel_commands-3">run_parallel_commands/3</a></td><td>Similar to <a href="#run_parallel_commands-2"><code>run_parallel_commands/2</code></a>, but also accepts an
  environment used for symbolic variable evaluation, exactly as described in
  <a href="#run_commands-3"><code>run_commands/3</code></a>.</td></tr>
<tr><td valign="top"><a href="#state_after-2">state_after/2</a></td><td>Returns the symbolic state after running a given command sequence,
  according to the state machine specification found in <code>Mod</code>.</td></tr>
<tr><td valign="top"><a href="#zip-2">zip/2</a></td><td>Behaves like <code>lists:zip/2</code>, but the input lists do no not necessarily
  have equal length.</td></tr>
</table>

<h2><a name="functions">Function Details</a></h2>

<h3 class="function"><a name="command_names-1">command_names/1</a></h3>
<div class="spec">
<p><pre>command_names(Cmds :: <a href="#type-command_list">command_list()</a> | <a href="#type-parallel_testcase">parallel_testcase()</a>) -&gt;
                 [mfa()]</pre></p>
</div><p>Extracts the names of the commands from a given command sequence, in
  the form of MFAs. It is useful in combination with functions such as
  <a href="proper.html#aggregate-2"><code>proper:aggregate/2</code></a> in order to collect statistics about command
  execution.</p>

<h3 class="function"><a name="commands-1">commands/1</a></h3>
<div class="spec">
<p><pre>commands(Mod :: <a href="#type-mod_name">mod_name()</a>) -&gt; <a href="proper_types.html#type-type">proper_types:type()</a></pre></p>
</div><p>A special PropEr type which generates random command sequences,
  according to an abstract state machine specification. The function takes as
  input the name of a callback module, which contains the state machine
  specification. The initial state is computed by <code>Mod:initial_state/0</code>.</p>

<h3 class="function"><a name="commands-2">commands/2</a></h3>
<div class="spec">
<p><pre>commands(Mod :: <a href="#type-mod_name">mod_name()</a>, InitialState :: <a href="#type-symbolic_state">symbolic_state()</a>) -&gt;
            <a href="proper_types.html#type-type">proper_types:type()</a></pre></p>
</div><p>Similar to <a href="#commands-1"><code>commands/1</code></a>, but generated command sequences always
  start at a given state. In this case, the first command is always
  <code>{init,InitialState}</code> and is used to correctly initialize the state
  every time the command sequence is run (i.e. during normal execution,
  while shrinking and when checking a counterexample). In this case,
  <code>Mod:initial_state/0</code> is never called.</p>

<h3 class="function"><a name="more_commands-2">more_commands/2</a></h3>
<div class="spec">
<p><pre>more_commands(N :: pos_integer(), CmdType :: <a href="proper_types.html#type-type">proper_types:type()</a>) -&gt;
                 <a href="proper_types.html#type-type">proper_types:type()</a></pre></p>
</div><p>Increases the expected length of command sequences generated from
  <code>CmdType</code> by a factor <code>N</code>.</p>

<h3 class="function"><a name="parallel_commands-1">parallel_commands/1</a></h3>
<div class="spec">
<p><pre>parallel_commands(Mod :: <a href="#type-mod_name">mod_name()</a>) -&gt; <a href="proper_types.html#type-type">proper_types:type()</a></pre></p>
</div><p>A special PropEr type which generates parallel testcases,
  according to an absract state machine specification. The function takes as
  input the name of a callback module, which contains the state machine
  specification. The initial state is computed by <code>Mod:initial_state/0</code>.</p>

<h3 class="function"><a name="parallel_commands-2">parallel_commands/2</a></h3>
<div class="spec">
<p><pre>parallel_commands(Mod :: <a href="#type-mod_name">mod_name()</a>,
                  InitialState :: <a href="#type-symbolic_state">symbolic_state()</a>) -&gt;
                     <a href="proper_types.html#type-type">proper_types:type()</a></pre></p>
</div><p>Similar to <a href="#parallel_commands-1"><code>parallel_commands/1</code></a>, but generated command sequences
  always start at a given state.</p>

<h3 class="function"><a name="run_commands-2">run_commands/2</a></h3>
<div class="spec">
<p><pre>run_commands(Mod :: <a href="#type-mod_name">mod_name()</a>, Cmds :: <a href="#type-command_list">command_list()</a>) -&gt;
                {<a href="#type-history">history()</a>, <a href="#type-dynamic_state">dynamic_state()</a>, <a href="#type-statem_result">statem_result()</a>}</pre></p>
</div><p>Evaluates a given symbolic command sequence <code>Cmds</code> according to the
   state machine specified in <code>Mod</code>. The result is a triple of the form<br>
   <code>{History, DynamicState, Result}</code>, where:
  <ul>
  <li><code>History</code> contains the execution history of all commands that were
    executed without raising an exception. It contains tuples of the form
    {<code><a href="#type-dynamic_state">dynamic_state()</a></code>, <code>term()</code>}, specifying the state prior to
    command execution and the actual result of the command.</li>
  <li><code>DynamicState</code> contains the state of the abstract state machine at
    the moment when execution stopped. In case execution has stopped due to a
    false postcondition, <code>DynamicState</code> corresponds to the state prior to
    execution of the last command.</li>
  <li><code>Result</code> specifies the outcome of command execution. It can be
    classified in one of the following categories:
    <ul>
    <li><b>ok</b>
      <p>All commands were successfully run and all postconditions were true.
      </p></li>
    <li><b>initialization error</b>
      <p>There was an error while evaluating the initial state.</p></li>
    <li><b>postcondition error</b>
      <p>A postcondition was false or raised an exception.</p></li>
    <li><b>precondition error</b>
      <p>A precondition was false or raised an exception.</p></li>
    <li><b>exception</b>
      <p>An exception was raised while running a command.</p></li>
    </ul></li>
  </ul></p>

<h3 class="function"><a name="run_commands-3">run_commands/3</a></h3>
<div class="spec">
<p><pre>run_commands(Mod :: <a href="#type-mod_name">mod_name()</a>,
             Cmds :: <a href="#type-command_list">command_list()</a>,
             Env :: <a href="proper_symb.html#type-var_values">proper_symb:var_values()</a>) -&gt;
                {<a href="#type-history">history()</a>, <a href="#type-dynamic_state">dynamic_state()</a>, <a href="#type-statem_result">statem_result()</a>}</pre></p>
</div><p> Similar to <a href="#run_commands-2"><code>run_commands/2</code></a>, but also accepts an environment,
  used for symbolic variable evaluation during command execution. The
  environment consists of <code>{Key::atom(), Value::term()}</code> pairs. Keys may be
  used in symbolic variables (i.e. <code>{var,Key}</code>) whithin the command sequence
  <code>Cmds</code>. These symbolic variables will be replaced by their corresponding
  <code>Value</code> during command execution.</p>

<h3 class="function"><a name="run_parallel_commands-2">run_parallel_commands/2</a></h3>
<div class="spec">
<p><pre>run_parallel_commands(Mod :: <a href="#type-mod_name">mod_name()</a>,
                      Testcase :: <a href="#type-parallel_testcase">parallel_testcase()</a>) -&gt;
                         {<a href="#type-history">history()</a>,
                          [<a href="#type-parallel_history">parallel_history()</a>],
                          <a href="#type-statem_result">statem_result()</a>}</pre></p>
</div><p>Runs a given parallel testcase according to the state machine
  specified in <code>Mod</code>. The result is a triple of the form<br>
  <code>{Sequential_history, Parallel_history, Result}</code>, where:
  <ul>
  <li><code>Sequential_history</code> contains the execution history of the
    sequential component.</li>
  <li><code>Parallel_history</code> contains the execution history of each of the
    concurrent tasks.</li>
  <li><code>Result</code> specifies the outcome of the attemp to serialize command
    execution, based on the results observed. It can be one of the following:
    <ul><li> <code>ok</code> </li><li> <code>no_possible_interleaving</code> </li></ul> </li>
  </ul></p>

<h3 class="function"><a name="run_parallel_commands-3">run_parallel_commands/3</a></h3>
<div class="spec">
<p><pre>run_parallel_commands(Mod :: <a href="#type-mod_name">mod_name()</a>,
                      X2 :: <a href="#type-parallel_testcase">parallel_testcase()</a>,
                      Env :: <a href="proper_symb.html#type-var_values">proper_symb:var_values()</a>) -&gt;
                         {<a href="#type-history">history()</a>,
                          [<a href="#type-parallel_history">parallel_history()</a>],
                          <a href="#type-statem_result">statem_result()</a>}</pre></p>
</div><p>Similar to <a href="#run_parallel_commands-2"><code>run_parallel_commands/2</code></a>, but also accepts an
  environment used for symbolic variable evaluation, exactly as described in
  <a href="#run_commands-3"><code>run_commands/3</code></a>.</p>

<h3 class="function"><a name="state_after-2">state_after/2</a></h3>
<div class="spec">
<p><pre>state_after(Mod :: <a href="#type-mod_name">mod_name()</a>, Cmds :: <a href="#type-command_list">command_list()</a>) -&gt;
               <a href="#type-symbolic_state">symbolic_state()</a></pre></p>
</div><p>Returns the symbolic state after running a given command sequence,
  according to the state machine specification found in <code>Mod</code>. The commands
  are not actually executed.</p>

<h3 class="function"><a name="zip-2">zip/2</a></h3>
<div class="spec">
<p><pre>zip(X :: [A], Y :: [B]) -&gt; [{A, B}]</pre></p>
</div><p>Behaves like <code>lists:zip/2</code>, but the input lists do no not necessarily
  have equal length. Zipping stops when the shortest list stops. This is
  useful for zipping a command sequence with its (failing) execution history.</p>
<hr>

<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
<p><i>Generated by EDoc</i></p>
</body>
</html>