<commit_before>Remote library interface
------------------------

The remote library interface provides means for having test libraries
on different machines than where Robot Framework itself is running,
and also for implementing libraries using other languages than the
natively supported Python and Java. For a test library user remote
libraries look pretty much the same as any other test library, and
developing test libraries using the remote library interface is also
very close to creating `normal test libraries`__.

__ `Creating test libraries`_

.. contents::
   :depth: 2
   :local:

Introduction
~~~~~~~~~~~~

There are two main reasons for using the remote library API:

* It is possible to have actual libraries on different machines than
  where Robot Framework is running. This allows interesting
  possibilities for distributed testing.

* Test libraries can be implemented using any language that supports
  `XML-RPC`_ protocol. Robot Framework 2.1 contains generic `remote
  servers`_ for Python/Jython and Ruby, and the community has implemented
  generic servers for other languages like Java, .NET and Perl.

The remote library interface is provided by the Remote library that is
one of the `standard libraries`_ starting from Robot Framework
2.1. This library does not have any keywords of its own, but it works
as a proxy between the core framework and keywords implemented
elsewhere. The Remote library interacts with actual library
implementations through `remote servers`_, and the Remote library and
servers communicate using a simple `remote protocol`_ on top of an
XML-RPC channel.  The high level architecture of all this is
illustrated in the picture below:

.. figure:: src/ExtendingRobotFramework/remote.png

   Robot Framework architecture with Remote library

.. note:: The remote client uses Python's standard xmlrpclib__ module. It does
          not support custom XML-RPC extensions implemented by some XML-RPC
          servers.

__ http://docs.python.org/2/library/xmlrpclib.html

Taking Remote library into use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Importing Remote library
''''''''''''''''''''''''

The Remote library needs to know the address of the remote server but
otherwise importing it and using keywords that it provides is no
different to how other libraries are used. If you need to use the Remote
library multiple times in a test suite, or just want to give it a more
descriptive name, you can import it using the `WITH NAME syntax`_.

.. table:: Importing Remote library
   :class: example

   =========  ===========  ========================  =========  =========
    Setting      Value               Value             Value      Value
   =========  ===========  ========================  =========  =========
   Library    Remote       \http://127.0.0.1:8270    WITH NAME  Example1
   Library    Remote       \http://example.com:7777  WITH NAME  Example2
   =========  ===========  ========================  =========  =========

The URL used by the first example above is also the default address
that the Remote library uses if no address is given. Similarly port
:code:`8270` is the port that remote servers are expected to use by default.
(82 and 70 are the ASCII codes of letters `R` and `F`, respectively.)

.. note:: When connecting to the local machine, it is recommended to use
          address :code:`127.0.0.1` instead of :code:`localhost`. This avoids
          address resolution that can be extremely slow `at least on Windows`__.
          Prior to Robot Framework 2.8.4 the Remote library itself used the
          potentially slow :code:`localhost` by default.


__ http://stackoverflow.com/questions/14504450/pythons-xmlrpc-extremely-slow-one-second-per-call

Starting and stopping remote servers
''''''''''''''''''''''''''''''''''''

Before the Remote library can be imported, the remote server providing
the actual keywords must be started.  If the server is started before
launching the test execution, it is possible to use the normal
:opt:`Library` setting like in the above example. Alternatively other
keywords, for example from OperatingSystem or SSH libraries, can start
the server up, but then you may need to use `Import Library keyword`__
because the library is not available when the test execution starts.

How a remote server can be stopped depends on how it is
implemented. Following methods work with the servers distributed with
Robot Framework:

* Regardless of the library used, remote servers provide :name:`Stop
  Remote Server` keyword that can be used from the test data.
* Remote servers have :code:`stop_remote_server` method in their
  XML-RPC interface.
* :code:`Ctrl-C` stops the server if it is running on a terminal
  window. Unfortunately this does not work with all servers on all
  operating systems.
* The server process can be terminated using tools provided by the
  operating system (e.g. :prog:`kill`).

.. note:: The server may be configured so that users cannot stop it with
          :name:`Stop Remote Server` keyword or :code:`stop_remote_server`
          method.

__ `Using Import Library keyword`_

Supported argument and return value types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Because the XML-RPC protocol does not support all possible object
types, the values transferred between the Remote library and remote
servers must be converted to compatible types. This applies to the
keyword arguments the Remote library passes to remote servers and to
the return values servers give back to the Remote library.

Both the Remote library and the Python remote server handle Python values
according to the following rules. Other remote servers should behave similarly.

* Strings, numbers and Boolean values are passed without modifications.
* Python :code:`None` is converted to an empty string.
* All lists, tuples, and other iterable objects (except strings and
  dictionaries) are passed as lists so that their contents are converted
  recursively.
* Dictionaries and other mappings are passed as dicts so that their keys are
  converted to strings and values converted to supported types recursively.
* Other types are converted to strings.

.. note:: Prior to Robot Framework 2.8.3, only lists, tuples, and dictionaries
          were handled according to the above rules. General iterables
          and mappings were not supported.

Using remote servers
~~~~~~~~~~~~~~~~~~~~

Robot Framework 2.1 includes remote server implementations written
both in Python and Ruby. These servers, as well as the example
libraries shown below and an example test case file, are
included in source distributions under :path:`tools/remoteserver`
directory and available also at
http://code.google.com/p/robotframework/wiki/RemoteLibrary.

The provided servers are designed so that it is easy to create test
libraries using them. With both of the servers the basic procedure is
as follows:

* Create a test library module or class similarly as a normal test
  library using the `static library API`_. With the Python server it
  is also possible to use the `hybrid library API`_.
* Import the remote server class and create an instance of it giving
  the library instance or module to it as an argument. The listening
  address and port, possibly got from the command line, can be given
  as optional arguments.

Both these steps can be done in the same module as illustrated by the
examples below. Executing these modules as scripts from the command
line will start the remote server so that it serves the keywords<commit_msg>UG: Documented how Remote interface handles binary data.<commit_after>Remote library interface
------------------------

The remote library interface provides means for having test libraries
on different machines than where Robot Framework itself is running,
and also for implementing libraries using other languages than the
natively supported Python and Java. For a test library user remote
libraries look pretty much the same as any other test library, and
developing test libraries using the remote library interface is also
very close to creating `normal test libraries`__.

__ `Creating test libraries`_

.. contents::
   :depth: 2
   :local:

Introduction
~~~~~~~~~~~~

There are two main reasons for using the remote library API:

* It is possible to have actual libraries on different machines than
  where Robot Framework is running. This allows interesting
  possibilities for distributed testing.

* Test libraries can be implemented using any language that supports
  `XML-RPC`_ protocol. Robot Framework 2.1 contains generic `remote
  servers`_ for Python/Jython and Ruby, and the community has implemented
  generic servers for other languages like Java, .NET and Perl.

The remote library interface is provided by the Remote library that is
one of the `standard libraries`_ starting from Robot Framework
2.1. This library does not have any keywords of its own, but it works
as a proxy between the core framework and keywords implemented
elsewhere. The Remote library interacts with actual library
implementations through `remote servers`_, and the Remote library and
servers communicate using a simple `remote protocol`_ on top of an
XML-RPC channel.  The high level architecture of all this is
illustrated in the picture below:

.. figure:: src/ExtendingRobotFramework/remote.png

   Robot Framework architecture with Remote library

.. note:: The remote client uses Python's standard xmlrpclib__ module. It does
          not support custom XML-RPC extensions implemented by some XML-RPC
          servers.

__ http://docs.python.org/2/library/xmlrpclib.html

Taking Remote library into use
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Importing Remote library
''''''''''''''''''''''''

The Remote library needs to know the address of the remote server but
otherwise importing it and using keywords that it provides is no
different to how other libraries are used. If you need to use the Remote
library multiple times in a test suite, or just want to give it a more
descriptive name, you can import it using the `WITH NAME syntax`_.

.. table:: Importing Remote library
   :class: example

   =========  ===========  ========================  =========  =========
    Setting      Value               Value             Value      Value
   =========  ===========  ========================  =========  =========
   Library    Remote       \http://127.0.0.1:8270    WITH NAME  Example1
   Library    Remote       \http://example.com:7777  WITH NAME  Example2
   =========  ===========  ========================  =========  =========

The URL used by the first example above is also the default address
that the Remote library uses if no address is given. Similarly port
:code:`8270` is the port that remote servers are expected to use by default.
(82 and 70 are the ASCII codes of letters `R` and `F`, respectively.)

.. note:: When connecting to the local machine, it is recommended to use
          address :code:`127.0.0.1` instead of :code:`localhost`. This avoids
          address resolution that can be extremely slow `at least on Windows`__.
          Prior to Robot Framework 2.8.4 the Remote library itself used the
          potentially slow :code:`localhost` by default.


__ http://stackoverflow.com/questions/14504450/pythons-xmlrpc-extremely-slow-one-second-per-call

Starting and stopping remote servers
''''''''''''''''''''''''''''''''''''

Before the Remote library can be imported, the remote server providing
the actual keywords must be started.  If the server is started before
launching the test execution, it is possible to use the normal
:opt:`Library` setting like in the above example. Alternatively other
keywords, for example from OperatingSystem or SSH libraries, can start
the server up, but then you may need to use `Import Library keyword`__
because the library is not available when the test execution starts.

How a remote server can be stopped depends on how it is
implemented. Following methods work with the servers distributed with
Robot Framework:

* Regardless of the library used, remote servers provide :name:`Stop
  Remote Server` keyword that can be used from the test data.
* Remote servers have :code:`stop_remote_server` method in their
  XML-RPC interface.
* :code:`Ctrl-C` stops the server if it is running on a terminal
  window. Unfortunately this does not work with all servers on all
  operating systems.
* The server process can be terminated using tools provided by the
  operating system (e.g. :prog:`kill`).

.. note:: The server may be configured so that users cannot stop it with
          :name:`Stop Remote Server` keyword or :code:`stop_remote_server`
          method.

__ `Using Import Library keyword`_

Supported argument and return value types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Because the XML-RPC protocol does not support all possible object
types, the values transferred between the Remote library and remote
servers must be converted to compatible types. This applies to the
keyword arguments the Remote library passes to remote servers and to
the return values servers give back to the Remote library.

Both the Remote library and the Python remote server handle Python values
according to the following rules. Other remote servers should behave similarly.

* Strings, numbers and Boolean values are passed without modifications.
* Python :code:`None` is converted to an empty string.
* All lists, tuples, and other iterable objects (except strings and
  dictionaries) are passed as lists so that their contents are converted
  recursively.
* Dictionaries and other mappings are passed as dicts so that their keys are
  converted to strings and values converted to supported types recursively.
* Strings containing bytes in the ASCII range that cannot be represented in
  XML (e.g. the null byte) are sent as `Binary objects`__ that internally use
  XML-RPC base64 data type. Received Binary objects are automatically converted
  to byte strings.
* Other types are converted to strings.

.. note:: Prior to Robot Framework 2.8.3, only lists, tuples, and dictionaries
          were handled according to the above rules. General iterables
          and mappings were not supported.

          Binary support is new in Robot Framework 2.8.4.

__ http://docs.python.org/2/library/xmlrpclib.html#binary-objects

Using remote servers
~~~~~~~~~~~~~~~~~~~~

Robot Framework 2.1 includes remote server implementations written
both in Python and Ruby. These servers, as well as the example
libraries shown below and an example test case file, are
included in source distributions under :path:`tools/remoteserver`
directory and available also at
http://code.google.com/p/robotframework/wiki/RemoteLibrary.

The provided servers are designed so that it is easy to create test
libraries using them. With both of the servers the basic procedure is
as follows:

* Create a test library module or class similarly as a normal test
  library using the `static library API`_. With the Python server it
  is also possible to use the `hybrid library API`_.
* Import the remote server class and create an instance of it giving
  the library instance or module to it as an argument. The listening
  address and port, possibly got from the command line, can be given
  as optional arguments.

Both these steps can be done in the same module as illustrated by the
examples below. Executing these modules as scripts from the command
line will start the remote server so that it serves the keywords
{'fraction_non_alphanumeric': 0.08716425619834711, 'fraction_numerical': 0.007102272727272727, 'mean_word_length': 4.050211933485491, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 7}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '978646', 'n_tokens_mistral': 3743, 'n_tokens_neox': 3549, 'n_words': 2084}