anchor.diff:              run_operations( Scenario
                             , T
                             , NewParams
  +                          , Options
                             , [{Description, Request, Pass}|Acc]
                             );
       _    -> [{Description, Request, ValidationResult}|Acc]
     end;
  -run_operations(_Scenario, [], _Params, Acc) ->
  +run_operations(_Scenario, [], _Params, _Options, Acc) ->
     Acc.
   
   make_request_url(Url = "http://" ++ _, _Params)  -> Url;
  
positive.code: 
  make_katt_response( #katt_response{headers=Hdrs0, body=RawBody0} = Res
                    , Params
                    , Parsers) ->
    Hdrs = [{K, recall(V, Params)} || {K, V} <- Hdrs0],
    RawBody = recall(RawBody0, Params),
    Res#katt_response{ body = maybe_parse_body(Hdrs, RawBody)
                     }.
  
  maybe_parse_body(_Hdrs, null) ->
    [];
  
negative.code: -define(SCENARIO_TIMEOUT,  120000).
  -define(REQUEST_TIMEOUT,   20000).
  
  -type katt_run_result() :: { nonempty_string()    % scenario name
                             , [ { string()         % operation description
                                 , #katt_request{}
                                 , pass | { fail
                                          , atom()  % reason
                                          , any()   % details
                                          }
                                 }
                               ]
                             } | { error
                                 , atom()           % reason
                                 , any()            % details
                                 }.
  
  %%%_* API ==============================================================
  -spec run(nonempty_string()) -> katt_run_result().
  
  %% @doc Run test scenario. Argument is the full path to the scenario file.
  %% The scenario file should be a KATT Blueprint file.
  %% @end
  run(Scenario) -> run(Scenario, []).
  
  -spec run(nonempty_string(), list()) -> katt_run_result().
  %% @doc Run test scenario. Argument is the full path to the scenario file.
  %% The scenario file should be a KATT Blueprint file.
  %% @end
  run(Scenario, Params) -> run(Scenario, Params, []).
  
  
  -spec run(nonempty_string(), list(), list()) -> katt_run_result().
  %% @doc Run test scenario. First argument is the full path to the scenario file.
  %% Second argument is a key-value list of parameters, such as hostname, port.
  %% You can also pass custom variable names (atoms) and values (strings).
  %% Third argument is a key-value list of special options such as custom
  %% parser to use instead of the built-in default parser (maybe_parse_body).
  %% @end
  run(Scenario, Params, Options) ->
    ScenarioTimeout = proplists:get_value( scenario_timeout
                                         , Options
                                         , ?SCENARIO_TIMEOUT
                                         ),
    spawn_link(?MODULE, run, [self(), Scenario, Params, Options]),
    receive {done, Result}    -> Result
    after   ScenarioTimeout -> {error, timeout, ScenarioTimeout}
    end.
  
  %%%_* Internal export --------------------------------------------------
  %% @private
  run(From, Scenario, ScenarioParams, ScenarioOptions) ->
    {ok, Blueprint} = katt_blueprint_parse:file(Scenario),
    Params = ordsets:from_list(make_params(ScenarioParams)),
    Options = make_options(ScenarioOptions),
    Result = {Scenario, run_scenario(Scenario, Blueprint, Params, Options)},
    From ! {done, Result}.
  
  %%%_* Internal =========================================================
  