<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Diplomats can code too! (Posts about integration testing)</title><link>https://wintermade.it/blog/</link><description></description><atom:link href="https://wintermade.it/blog/categories/integration-testing.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 03 Nov 2019 15:11:25 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Embeddable scripting languages are for integration testing too!</title><link>https://wintermade.it/blog/posts/embeddable-scripting-languages-are-for-integration-testing-too.html</link><dc:creator>Alessandro Balzano</dc:creator><description>&lt;div&gt;&lt;p&gt;tl;dr needed some fake clients, went the scripting route instead of
building several little executables.&lt;/p&gt;
&lt;div class="section" id="what"&gt;
&lt;h2&gt;What?&lt;/h2&gt;
&lt;p&gt;At work, among other things, I'm working on a debugging/postmortem
analysis component for a bigger, complex and not-so-tested system. This
little service is really important and used during integration tests, so
"it has to work".&lt;/p&gt;
&lt;p&gt;While I managed to find and remove lots of bugs early (based TDD!), some
behaviors of the service "as a whole" were not tested as much as I'd
like.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="explaining-the-service-a-little-more"&gt;
&lt;h2&gt;Explaining the service a little more&lt;/h2&gt;
&lt;p&gt;Please, don't close the tab and keep reading. I need to explain some
more details about the service I want to put under test.&lt;/p&gt;
&lt;p&gt;This little "thing" receives messages via ZeroMQ, has to write them to
files and stream the received information to other clients to do some
realtime graphs/visual analysis, or whatever they prefer. Clients can
communicate to the component using a simple, custom C++ library that
"hides" the ZeroMQ client code, so we have to test it, that messages are
received correctly and that the commands sent by clients are executed.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For the sake of simplicity, and to give you both an idea of
what I'm discussing and a runnable proof of concept, I wrote
a toy example on&lt;/em&gt; &lt;a class="reference external" href="https://bitbucket.com/alfateam123/chaiscript-integration-poc"&gt;Bitbucket&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;An example of the library code is the following:&lt;/p&gt;
&lt;pre class="code cpp"&gt;&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-1"&gt;&lt;/a&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;ClientClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;logValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;value_to_send&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-2"&gt;&lt;/a&gt;  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"sending value: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;value_to_send&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-3"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-4"&gt;&lt;/a&gt;  &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-5"&gt;&lt;/a&gt;  &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value_to_send&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-6"&gt;&lt;/a&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-7"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-8"&gt;&lt;/a&gt;  &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-10"&gt;&lt;/a&gt;  &lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_818321cb254844e38d648de4db0aed2a-11"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="the-idea"&gt;
&lt;h2&gt;The idea&lt;/h2&gt;
&lt;p&gt;At first, I tried to simulate as much cases as possible in a single
"testing client" -a fake program to simulate actual clients-, but I
understood the hard way that it was a very stupid idea: tests became
difficult to extend very, very soon, and it was difficult to modify it
to test something without breaking something else. After the
enlightment, I started thinking about having several fake clients, each
one tailored on the situation I wanted to test (message bursts, ntp
client/server malfunctions, etc).&lt;/p&gt;
&lt;p&gt;I didn't want to include these little executables to my daily dev build,
though: it'd take too much time to do a full rebuild of the system, and
time is precious. This constraint made me think about using a scripting
language: "just write a script in some sort of DSL and you're done", I
thought.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chaiscript-or-extending-an-embeddable-language"&gt;
&lt;h2&gt;ChaiScript, or: extending an embeddable language&lt;/h2&gt;
&lt;p&gt;So, I started thinking about how to implement such a language. How
difficult it could be? The more I though about it, the more use-cases
and features I deemed necessary. From a bunch of &lt;tt class="docutils literal"&gt;log*&lt;/tt&gt; functions, it
evolved into a limited but general-purpose language with variables,
functions and cycles. Building your own language is a cool, fun and
"formative" experience, I didn't have the time to actually write an
interpreter or a compiler &lt;em&gt;and&lt;/em&gt; maintain it &lt;em&gt;in addition to the real
project.&lt;/em&gt; The right thing to do was to pick an existing solution and
integrate it inside the real project.&lt;/p&gt;
&lt;p&gt;So, after a little searching on the Wired, I came across
&lt;a class="reference external" href="https://github.com/chaiscript/chaiscript"&gt;ChaiScript&lt;/a&gt;, a simple
Javascript-like language written in C++, designed to be embedded by C++
applications. The usual &lt;cite&gt;cmake . &amp;amp;&amp;amp; make &amp;amp;&amp;amp; make install&lt;/cite&gt; will build
and install it from sources.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="let-s-write-the-server-first"&gt;
&lt;h2&gt;Let's write the server first...&lt;/h2&gt;
&lt;p&gt;As said before, the server is just a simple ZeroMQ ROUTER in a
DEALER-ROUTER communication scheme. For the sake of simplicity, in this
article we will work on a simplified example, a proof of concept.&lt;/p&gt;
&lt;p&gt;The protocol between the server and its clients is very simple: messages
cannot be bigger than 20 bytes, and two kinds of payloads can be sent.&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_a632ae861c0a4076898c8e7e83464094-1"&gt;&lt;/a&gt;byte  0: message_type (0=ascii, 1=number)
&lt;a name="rest_code_a632ae861c0a4076898c8e7e83464094-2"&gt;&lt;/a&gt;bytes 1-20: payload
&lt;/pre&gt;&lt;p&gt;If &lt;tt class="docutils literal"&gt;message_type&lt;/tt&gt; is 0, an ASCII string is sent to the server, if 1
it's a unsigned int number between 0 and 255 -only one byte will be used
to store it-.&lt;/p&gt;
&lt;pre class="code cpp"&gt;&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;zmq.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-3"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstring&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-4"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-5"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-6"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_ctx_new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-7"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;socket_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ZMQ_ROUTER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-8"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-9"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// set a timeout&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-10"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;recv_timeout_ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-11"&gt;&lt;/a&gt;  &lt;span class="n"&gt;zmq_setsockopt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ZMQ_RCVTIMEO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;recv_timeout_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-12"&gt;&lt;/a&gt;                 &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recv_timeout_ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-13"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-14"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"tcp://127.0.0.1:6987"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-15"&gt;&lt;/a&gt;    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"err: could not bind, "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;zmq_strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_errno&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-16"&gt;&lt;/a&gt;              &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-17"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-18"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-19"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-20"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// needed to skip identity messages&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-21"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_recv_message_identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-22"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;timeoutted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-23"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-24"&gt;&lt;/a&gt;  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;timeoutted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-25"&gt;&lt;/a&gt;    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-26"&gt;&lt;/a&gt;    &lt;span class="n"&gt;bzero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-27"&gt;&lt;/a&gt;    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;recv_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-28"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-29"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recv_res&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-30"&gt;&lt;/a&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_errno&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// EAGAIN&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-31"&gt;&lt;/a&gt;        &lt;span class="n"&gt;timeoutted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-32"&gt;&lt;/a&gt;        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-33"&gt;&lt;/a&gt;      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-34"&gt;&lt;/a&gt;        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"err: could not receive ["&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;zmq_errno&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"] "&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-35"&gt;&lt;/a&gt;                  &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;zmq_strerror&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq_errno&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-36"&gt;&lt;/a&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-37"&gt;&lt;/a&gt;      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-38"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-39"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-40"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;// skip identity messages: they're not the payload we are looking for,&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-41"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;//      and we don't need to do identity-based logic in this PoC.&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-42"&gt;&lt;/a&gt;    &lt;span class="n"&gt;is_recv_message_identity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_recv_message_identity&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-43"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_recv_message_identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-44"&gt;&lt;/a&gt;      &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-45"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-46"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-47"&gt;&lt;/a&gt;      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"received a string!"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-48"&gt;&lt;/a&gt;      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"the received string is: &amp;gt;&amp;gt;&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-49"&gt;&lt;/a&gt;                &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-50"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-51"&gt;&lt;/a&gt;      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"received a number!"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-52"&gt;&lt;/a&gt;      &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"the received number is: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-53"&gt;&lt;/a&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-54"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-55"&gt;&lt;/a&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-56"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sock_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket_&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-57"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sock_res&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-58"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sock_res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-59"&gt;&lt;/a&gt;  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ctx_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq_ctx_shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-60"&gt;&lt;/a&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ctx_res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_a584562d34d1449f811186adbc8008c5-61"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="then-the-client-script-runner"&gt;
&lt;h2&gt;... then, the client script runner&lt;/h2&gt;
&lt;p&gt;Being a proof of concept discussed here, we'll keep things simple and
limit our example to just two functions: &lt;tt class="docutils literal"&gt;logDebug(str)&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;logValue(unsigned int)&lt;/tt&gt;, that send a string or an unsigned int to the
server via ZeroMQ.&lt;/p&gt;
&lt;pre class="code cpp"&gt;&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-1"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;chaiscript/chaiscript.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-2"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;chaiscript/utility/utility.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-3"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-4"&gt;&lt;/a&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;mahlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-6"&gt;&lt;/a&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-7"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// handle parameters. if no parameter is given, use "test.chai"&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-8"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// as default script name.&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-9"&gt;&lt;/a&gt;  &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;script_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test.chai"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-10"&gt;&lt;/a&gt;  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-11"&gt;&lt;/a&gt;    &lt;span class="n"&gt;script_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-12"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-13"&gt;&lt;/a&gt;  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-14"&gt;&lt;/a&gt;    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"usage: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;" &amp;lt;script.chai&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-15"&gt;&lt;/a&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-16"&gt;&lt;/a&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-17"&gt;&lt;/a&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-18"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// create the ChaiScript interpreter&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-19"&gt;&lt;/a&gt;  &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ChaiScript&lt;/span&gt; &lt;span class="n"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-20"&gt;&lt;/a&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-21"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// extend ChaiScript with our ClientClass class,&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-22"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// so it can recognize our class' usage in the module,&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-23"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// call the right function at the right time, etc.&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-24"&gt;&lt;/a&gt;  &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ModulePtr&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ModulePtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-25"&gt;&lt;/a&gt;  &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;add_class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClientClass&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-26"&gt;&lt;/a&gt;     &lt;span class="s"&gt;"ClientClass"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-27"&gt;&lt;/a&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ClientClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-28"&gt;&lt;/a&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ClientClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;logDebug&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"logDebug"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-29"&gt;&lt;/a&gt;       &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chaiscript&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ClientClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;logValue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"logValue"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-30"&gt;&lt;/a&gt;     &lt;span class="p"&gt;});&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-31"&gt;&lt;/a&gt;  &lt;span class="n"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-32"&gt;&lt;/a&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-33"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// the (augmented) interpreter picks the script and executes it.&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-34"&gt;&lt;/a&gt;  &lt;span class="c1"&gt;// it never asked for this, by the way.&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-35"&gt;&lt;/a&gt;  &lt;span class="n"&gt;chai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eval_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;script_name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-36"&gt;&lt;/a&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-37"&gt;&lt;/a&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a name="rest_code_9f3fcd02b64c45469f4faa80dae489f4-38"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class="section" id="time-to-write-scripts"&gt;
&lt;h2&gt;Time to write scripts!&lt;/h2&gt;
&lt;p&gt;Let's now write some scripts and test the whole system!&lt;/p&gt;
&lt;pre class="code js"&gt;&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// define a simple function&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-2"&gt;&lt;/a&gt;&lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-3"&gt;&lt;/a&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-4"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-6"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// define a client, directly inside the script!&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-7"&gt;&lt;/a&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ClientClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"tcp://127.0.0.1:6987"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-8"&gt;&lt;/a&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-9"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// call client's methods.&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-10"&gt;&lt;/a&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-11"&gt;&lt;/a&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logDebug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"from chai via zmq!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_b93cb038b7194b12bd67cea835ed0cb8-12"&gt;&lt;/a&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logDebug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hey, what happens if I send a string that is obviously longer than 18 characters? eh? EEEEHHHH???"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;What does the server prints out on the console?&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-1"&gt;&lt;/a&gt;# the client is run as:
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-2"&gt;&lt;/a&gt;# LD_LIBRARY_PATH="/home/winter/built/chai/lib/chaiscript/" ./client test.chai
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-4"&gt;&lt;/a&gt;[winter@timeofeve] [/dev/pts/4] [master]
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-5"&gt;&lt;/a&gt;[~/blogging/chai-poc]&amp;gt; make run_server
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-6"&gt;&lt;/a&gt;./server
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-7"&gt;&lt;/a&gt;received a number!
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-8"&gt;&lt;/a&gt;the received number is: 71
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-9"&gt;&lt;/a&gt;received a string!
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-10"&gt;&lt;/a&gt;the received string is: &amp;gt;&amp;gt;&amp;gt;from chai via zmq!&amp;lt;&amp;lt;&amp;lt;
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-11"&gt;&lt;/a&gt;received a string!
&lt;a name="rest_code_f01d418935b144a4827d3b4abba69e1b-12"&gt;&lt;/a&gt;the received string is: &amp;gt;&amp;gt;&amp;gt;hey, what happens &amp;lt;&amp;lt;&amp;lt;
&lt;/pre&gt;&lt;p&gt;Let's now show another script we can run.&lt;/p&gt;
&lt;pre class="code js"&gt;&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;// define a client, directly inside the script!&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-2"&gt;&lt;/a&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ClientClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"tcp://127.0.0.1:6987"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-4"&gt;&lt;/a&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logDebug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-5"&gt;&lt;/a&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-7"&gt;&lt;/a&gt;    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-9"&gt;&lt;/a&gt;
&lt;a name="rest_code_e1b9574ff32c4e4bbdcaf32b0db223c9-10"&gt;&lt;/a&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logDebug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"goodbye!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;And the result is...&lt;/p&gt;
&lt;pre class="code text"&gt;&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-1"&gt;&lt;/a&gt;# the client is run as:
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-2"&gt;&lt;/a&gt;# LD_LIBRARY_PATH="/home/winter/built/chai/lib/chaiscript/" ./client wow.chai
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-3"&gt;&lt;/a&gt;
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-4"&gt;&lt;/a&gt;[winter@timeofeve] [/dev/pts/4]
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-5"&gt;&lt;/a&gt;[~/blogging/chai-poc]&amp;gt; make run_server
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-6"&gt;&lt;/a&gt;./server
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-7"&gt;&lt;/a&gt;received a string!
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-8"&gt;&lt;/a&gt;the received string is: &amp;gt;&amp;gt;&amp;gt;hello!&amp;lt;&amp;lt;&amp;lt;
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-9"&gt;&lt;/a&gt;received a number!
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-10"&gt;&lt;/a&gt;the received number is: 65
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-11"&gt;&lt;/a&gt;[snip]
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-12"&gt;&lt;/a&gt;received a number!
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-13"&gt;&lt;/a&gt;the received number is: 91
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-14"&gt;&lt;/a&gt;received a string!
&lt;a name="rest_code_be03ccd9d8a240f7898a5cb385ac5006-15"&gt;&lt;/a&gt;the received string is: &amp;gt;&amp;gt;&amp;gt;goodbye!&amp;lt;&amp;lt;&amp;lt;
&lt;/pre&gt;&lt;p&gt;What's the magic? We were able to write two scripts in a higher-level
language and use the same application to run them, without even
compiling once!&lt;/p&gt;
&lt;p&gt;Would you want to test this automatically, you may write a simple script
in Python that starts the server, launches the client with the right script
and then checks the content of the files generated by the server!
That's just an idea, though: your needs define how you'd write your integration
tests!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-nice-turnout-faster-experimentation-and-bug-hunting"&gt;
&lt;h2&gt;The nice turnout: faster experimentation and bug-hunting&lt;/h2&gt;
&lt;p&gt;It didn't took long to discover -and be favourably surprised!- that the new
scripted client allows for a lot of experimentation.&lt;/p&gt;
&lt;p&gt;In particular, I'm now working on the graphical user interface of one of
the systems that receive data from the server, and it let me check edge
cases in the graphs interaction, in real time.&lt;/p&gt;
&lt;p&gt;The workflow is very simple:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Have a doubt/want to test a different use case&lt;/li&gt;
&lt;li&gt;Write a simple script, changing the order of the function calls, how
data are generated, etc&lt;/li&gt;
&lt;li&gt;Run the new script, with the same client(!)&lt;/li&gt;
&lt;li&gt;Check how GUI reacts and fix glitches&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, you now have both some code that can be run to verify that issues
are solved. Easy and useful, isn't it?&lt;/p&gt;
&lt;p&gt;I'll throw it in too: as the whole thing is written in C++, I can use &lt;a class="reference external" href="https://wintermade.it/blog/posts/suzuha-a-shim-for-gettimeofday.html"&gt;Suzuha&lt;/a&gt; (with a
couple of ad-hoc function calls) inside the host application. Suzuha is a simple
shim for gettimeofday(3) and settimeofday(3), so I can make clients send
messages from the past (or the future!) without having to recompile them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="nice-isn-t-it-a-bit-overkill-though"&gt;
&lt;h2&gt;Nice. Isn't it a bit overkill though?&lt;/h2&gt;
&lt;p&gt;Probably. I just want to give my clients something that works. Being
able to anticipate possible problems and be sure that bugs found on the
field won't reappear anymore is very important, and I think that
thorough testing is one of the best ways to achieve it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Do you like the idea? Do you want to suggest something better, or share your experience?&lt;/em&gt;
&lt;em&gt;Send me a&lt;/em&gt; &lt;a class="reference external" href="https://twitter.com/alfateam123"&gt;tweet&lt;/a&gt; &lt;em&gt;, or consider offering me a&lt;/em&gt; &lt;a class="reference external" href="https://www.ko-fi.com/alessandrobalzano"&gt;Ko-Fi&lt;/a&gt; !&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</description><category>chaiscript</category><category>integration testing</category><guid>https://wintermade.it/blog/posts/embeddable-scripting-languages-are-for-integration-testing-too.html</guid><pubDate>Mon, 28 Mar 2016 13:09:12 GMT</pubDate></item></channel></rss>