<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
    <title type="text">blog. Ivan De Marino</title>
    <subtitle type="html">Converting caffeine into Code, most of the time...</subtitle>
    <updated>2013-05-11T03:09:00Z</updated>
    <id>tag:blog.ivandemarino.me,2013-05-11:atom.xml</id>
    <link rel="alternate" type="text/html" hreflang="en" href="http://blog.ivandemarino.me/" />
    
    
    <rights>Copyright (c) 2013</rights>
    <generator uri="http://blog.ivandemarino.me/" version="1.0">
        Bloggart 1.0
    </generator>
    
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/BlogIvanDeMarino" /><feedburner:info uri="blogivandemarino" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-sa/3.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><entry>
        <title>Me @ Selenium Camp 2013</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/m_2OQq0M2Os/Me-Selenium-Camp-2013" />
        <id>tag:blog.ivandemarino.me,2013-05-10:post:342001</id>
        <updated>2013-05-11T03:09:25Z</updated>
        <published>2013-03-03T23:44:11Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;&lt;a href="http://seleniumcamp.com/"&gt;Selenium Camp 2013&lt;/a&gt; has been a great experience. Not only I hanged out with great people, but, for the first time in my life, I also got to &lt;em&gt;savour&lt;/em&gt; a little bit of &lt;a href="http://en.wikipedia.org/wiki/Ukraine"&gt;Ukraine&lt;/a&gt; in &lt;a href="http://en.wikipedia.org/wiki/Kiev"&gt;Kiev&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;VERY friendly people (really friendly). GREAT food. WELL-ORGANISED conference.
&lt;/p&gt;
&lt;p&gt;What else could I ask for?
&lt;/p&gt;

&lt;h3&gt;My talk&lt;/h3&gt;
&lt;p&gt;The title of my talk is &lt;strong&gt;Getting Started with GhostDriver (and my experience working on it!)&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;UPDATE: here is the video:
   &lt;div class="img"&gt;
   &lt;iframe width="450" height="254" frameborder="0" src="http://video.yandex.ru/iframe/xpinjection/3cjz2f3n8c.7028/"&gt;&lt;/iframe&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Videos of the other talks can be found &lt;a href="http://video.yandex.ru/users/xpinjection/collection/11/"&gt;here&lt;/a&gt;.
   Here are the slides:
   &lt;div class="img"&gt;
   &lt;iframe src="https://docs.google.com/presentation/d/11-AQ9PvdjffoAT5Gqbczmgth9afGo_8zsYlCUpu5rDI/embed?start=false&amp;loop=false&amp;delayms=5000" frameborder="0" width="480" height="389" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"&gt;&lt;/iframe&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;You can find them also on &lt;a href="http://bit.ly/VgKsYm"&gt;Google Drive&lt;/a&gt; and &lt;a href="https://speakerdeck.com/detronizator/getting-started-with-ghostdriver"&gt;Speaker Deck&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;del&gt;&lt;strong&gt;Video will be available soon&lt;/strong&gt;: the organisers have recorded every session and I guess it's just a matter of time.&lt;/del&gt; Added. Scroll above.
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/m_2OQq0M2Os" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2013/03/03/Me-Selenium-Camp-2013</feedburner:origLink></entry>
    
    <entry>
        <title>I'm off. See you in 2 weeks.</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/CLNjrAGaO4A/I-m-off-See-you-in-2-weeks" />
        <id>tag:blog.ivandemarino.me,2013-03-28:post:344001</id>
        <updated>2013-03-29T01:53:06Z</updated>
        <published>2013-03-29T01:53:06Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;This message is for the few souls that care. This is for the few people that maybe are waiting for me to fix/implement stuff on &lt;a href="https://github.com/detro/ghostdriver"&gt;GhostDriver&lt;/a&gt; or &lt;a href="https://github.com/ariya/phantomjs"&gt;PhantomJS&lt;/a&gt; (for the latter you have coverage, as the team on that is rich of geniuses - so you won't miss my average-hood).
&lt;/p&gt;
&lt;p&gt;I'm &lt;strong&gt;getting married&lt;/strong&gt; (crazy, right?) and will be mostly off-line. I should be back from the second week of April.
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="http://blog.fashionwindows.com/wp-content/uploads/2010/08/exchanging_rings.jpg" /&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Surely there will be the usual &lt;em&gt;casual-tweet&lt;/em&gt; but nothing major.
&lt;/p&gt;
&lt;p&gt;See ya!
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/CLNjrAGaO4A" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2013/03/29/I-m-off-See-you-in-2-weeks</feedburner:origLink></entry>
    
    <entry>
        <title>BST traversal without stack or recursion (?)</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/Z5jO8-A3ChY/BST-traversal-wihtout-stack-or-recursion" />
        <id>tag:blog.ivandemarino.me,2013-03-23:post:336001</id>
        <updated>2013-03-24T01:40:23Z</updated>
        <published>2012-08-06T20:47:17Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;&lt;strong&gt;SPOILER&lt;/strong&gt;: &lt;em&gt;this article assumes quite a lot of things about your knowledge of binary trees and data structure. I won't spend much time introducing concepts. Deal with it.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;Some time ago I had the pleasure to meet with &lt;a href="http://chrislord.net/blog/"&gt;Chris Lord&lt;/a&gt;, who introduced me to the concept of Binary Tree Traversal without using neither a stack/queue or recursion.
&lt;/p&gt;
&lt;p&gt;The list of requirements that such algorithm has to fulfil:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Constant Space: no extra data structure to do the traversal
 &lt;/li&gt;

 &lt;li&gt;
     Non-destructive: once finished, the tree needs to be exactly how it was before the visit
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sounded &lt;em&gt;crazy&lt;/em&gt; initially, but than I looked into it more deeply and discovered, thanks to some pointers from &lt;a href="http://twitter.com/lucabox"&gt;Luca Colantonio&lt;/a&gt;, that there is an algorithm &lt;em&gt;in literature&lt;/em&gt; that does just that: &lt;strong&gt;Morris In-Order&lt;/strong&gt; Traversal.
&lt;/p&gt;
&lt;p&gt;Morris does just that - and a very good description of how it works can be found &lt;a href="http://stackoverflow.com/a/5506601/1389112"&gt;on Stack Overflow&lt;/a&gt;. I suggest you have a good read and come back: pointless of me to repeat it here.
&lt;/p&gt;
&lt;p&gt;...
&lt;/p&gt;
&lt;p&gt;You back? Great!
&lt;/p&gt;
&lt;p&gt;So, before "discovering" the Morris algorithm, I was trying to write a solution myself. My basic idea was to:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     Move downwards
 &lt;/li&gt;

 &lt;li&gt;
     Manipulate pointers to the branch we are about to explore, to point backward so we have "a way back"
 &lt;/li&gt;

 &lt;li&gt;
     Restore once done with that branch
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At that stage, it had not occur to me to try to manipulate the entire tree structure like Morris does: I wanted to be very subtle, with the data structure resembling the original tree (though, with backward pointers).
&lt;/p&gt;
&lt;p&gt;The key issue I hit? &lt;strong&gt;Going Backward&lt;/strong&gt;. Once I'm done visiting the branches of a node, I need to go back to the parent (to which I have a pointer too), and restore the structure.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But HOW am I going to reconstruct the tree?&lt;/strong&gt; How do I know if the Branch I just visited was the &lt;em&gt;left&lt;/em&gt; or the &lt;em&gt;right&lt;/em&gt; branch of the parent I want to move back to?
&lt;/p&gt;

&lt;h2&gt;Downsize the problem&lt;/h2&gt;
&lt;p&gt;In a general Binary Tree, there is no guarantee of the order and distribution of nodes. It's just a tree where every node has 0, 1 or 2 child nodes. I didn't have any "rule" on which to &lt;strong&gt;build a backward-restoring logic&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;But then I had an idea: what about &lt;a href="http://en.wikipedia.org/wiki/Binary_search_tree"&gt;BSTs (Binary Search Tree)&lt;/a&gt;? In those trees, there is a strong order relationship between a node and its childs.
&lt;/p&gt;
&lt;p&gt;This means that at any moment in time, once I'm done visiting a branch, I can reconstruct &lt;em&gt;where I'm coming from&lt;/em&gt;, looking at the values of the parent and the child:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;parent-&amp;gt;value &amp;gt; child-&amp;gt;value ? is_left_child : is_right_child
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, so I wrote the &lt;strong&gt;De Marino BST Post-Order Traversal&lt;/strong&gt; algorithm:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;de_marino_bst_post_order_traversal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;//&amp;lt; current node&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;//&amp;lt; parent of current node&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;//&amp;lt; next node to traversal (but sometimes, just temp variable)&lt;/span&gt;&lt;br /&gt;    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DOWN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;//&amp;lt; direction in which we are moving&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DOWN&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class="c1"&gt;// Go down left&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;par&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;}&lt;/span&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;dir&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DOWN&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class="c1"&gt;// Go down right&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;par&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&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;br /&gt;            &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&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;br /&gt;&lt;br /&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class="c1"&gt;// Go down right, coming from left&lt;/span&gt;&lt;br /&gt;                &lt;span class="c1"&gt;// NOTE: order gives us a hint about where we come from&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DOWN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// hold the way back&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// store the way back in the right child of par now&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&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;br /&gt;                &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br /&gt;                    &lt;span class="c1"&gt;// Go up, coming from left&lt;/span&gt;&lt;br /&gt;                    &lt;span class="c1"&gt;// NOTE: order gives us a hint about where we come from&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&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;br /&gt;                    &lt;span class="c1"&gt;// Go up, coming from right&lt;/span&gt;&lt;br /&gt;                    &lt;span class="c1"&gt;// NOTE: order gives us a hint about where we come from&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                    &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class="n"&gt;par&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class="p"&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;par&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;curr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;value&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;br /&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;Now, I'm almost 100% sure that I'm not the first one to &lt;em&gt;stumble&lt;/em&gt; into something like this, but for now I'm unable to find anything in literature - &lt;em&gt;cough&lt;/em&gt; ... Google ... &lt;em&gt;cough&lt;/em&gt; .
&lt;/p&gt;

&lt;h2&gt;An advantage over Morris&lt;/h2&gt;
&lt;p&gt;Yes, this algorithm requires the &lt;strong&gt;strong condition of BST&lt;/strong&gt; while Morris works with any Binary Tree. That's a given. But this algorithm is also &lt;strong&gt;faster&lt;/strong&gt;: it doesn't go deep into the tree to find the rightmost left child of a node, like Morris. From a quick look &lt;strong&gt;the computation is linear - O(n)&lt;/strong&gt;: every node is visited only once. But maybe I'm overlooking something in Morris.
&lt;/p&gt;

&lt;h2&gt;Far from perfect&lt;/h2&gt;
&lt;p&gt;I'm also sure that this algorithm is &lt;strong&gt;far from bug-less&lt;/strong&gt;: I have spent on it less than 24h between coding and thinking. So, please, to all the Computer Scientists people out there: let me know your thoughts and critics. This is a great way to spend some of that theory that we have in our heads.
&lt;/p&gt;
&lt;p&gt;I have added this code to my &lt;a href="https://github.com/detro/coding-exercises/commits/master"&gt;coding exercises&lt;/a&gt; repo on GitHub, if you want to try it out (check latest commits).
&lt;/p&gt;
&lt;p&gt;Now, as I expect, feel free to ignore my warnings and start your opinionated trashing - I'm pretty confident I'd deserve it. :)
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/Z5jO8-A3ChY" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2012/08/06/BST-traversal-wihtout-stack-or-recursion</feedburner:origLink></entry>
    
    <entry>
        <title>[UPDATED - PhantomJS 1.9.0] GhostDriver 1.0.3 is out!</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/J-2HPwXY_oE/GhostDriver-1-0-3-is-out" />
        <id>tag:blog.ivandemarino.me,2013-03-22:post:343001</id>
        <updated>2013-03-22T23:55:50Z</updated>
        <published>2013-03-19T02:25:19Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;After few months of endless nights trying to figure out what I screwed up and where, I'm finally happy (enough) to release &lt;strong&gt;GhostDriver 1.0.3&lt;/strong&gt; into the wild.
&lt;/p&gt;
&lt;p&gt;This release is an &lt;em&gt;hardening release&lt;/em&gt;: this means that it's focused on bug-fixing and very little new features have been added.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GhostDriver 1.0.3&lt;/strong&gt; &lt;del&gt;will be part of the upcoming &lt;strong&gt;PhantomJS 1.9&lt;/strong&gt; release, do in few days&lt;/del&gt; is now part of &lt;strong&gt;PhantomJS 1.9.0&lt;/strong&gt;, and you can download binaries for various platform from &lt;a href="https://code.google.com/p/phantomjs/downloads/list"&gt;https://code.google.com/p/phantomjs/downloads/list&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="http://dummyimage.com/500x220/383b38/00ff00.png&amp;text=1.0.3" /&gt;
   &lt;/div&gt;
   If you want to know what made it for the &lt;code&gt;1.0.3&lt;/code&gt; cut, take a look at the &lt;a href="https://github.com/detro/ghostdriver/blob/master/CHANGELOG.md"&gt;Changelog&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;I apologise in advance for whom have seen his "pet issue" not being implemented/fixed/addressed for this release, but it's only one of me.
&lt;/p&gt;
&lt;p&gt;I'd like to take the time to thank the few brave souls that have contributed to this release with their code. In chronological contribution order:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;a href="https://github.com/garyd203"&gt;garyd203&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/c089"&gt;Christoph Neuroth&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/nathandace"&gt;Nathan Dace&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/loduis"&gt;Loduis Madariaga Barrios&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/benmccann"&gt;Ben McCann&lt;/a&gt;
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks guys! &lt;em&gt;Keep being awesome!&lt;/em&gt;
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/J-2HPwXY_oE" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2013/03/19/GhostDriver-1-0-3-is-out</feedburner:origLink></entry>
    
    <entry>
        <title>Console++ - enhance your console</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/480sUScvzU0/Console---enhance-your-console" />
        <id>tag:blog.ivandemarino.me,2013-02-18:post:341001</id>
        <updated>2013-02-18T09:05:48Z</updated>
        <published>2013-02-18T09:05:48Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;I need a logger for &lt;a href="https://github.com/detro/ghostdriver"&gt;GhostDriver&lt;/a&gt; but I'm too lazy to figure out how to use a nice, proper logging library. Plus I'm a BIG fun of old-school-debugging: I just substituted all the &lt;code&gt;printf()&lt;/code&gt; calls with &lt;code&gt;console.log&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;So I decide to make every JavaScript developer &lt;em&gt;shiver in disgust&lt;/em&gt; and wrote a small library that enhances the global &lt;code&gt;console&lt;/code&gt; object.
&lt;/p&gt;
&lt;p&gt;This tiny library is called &lt;a href="https://github.com/detro/consoleplusplus"&gt;Console++&lt;/a&gt; and works with &lt;a href="http://nodejs.org"&gt;NodeJS&lt;/a&gt;, &lt;a href="http://phantomjs.org"&gt;PhantomJS&lt;/a&gt; and any decent JavaScript runtime.
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="https://raw.github.com/detro/consoleplusplus/master/README.pics/console++-1.png" /&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;It does output colouring, adds timestamps and log level to the lines, and can be used to redirect the output to other media than the console (just register a callback). On &lt;code&gt;node&lt;/code&gt;, just type &lt;code&gt;npm install consoleplusplus&lt;/code&gt; to get started.
&lt;/p&gt;
&lt;p&gt;It's so simple that the &lt;a href="https://github.com/detro/consoleplusplus/blob/master/README.md"&gt;README&lt;/a&gt; is more than enough to use it.
&lt;/p&gt;
&lt;p&gt;It's under &lt;a href="http://en.wikipedia.org/wiki/BSD_licenses"&gt;BSD license&lt;/a&gt;, so you can have fun with it.
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/480sUScvzU0" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2013/02/18/Console---enhance-your-console</feedburner:origLink></entry>
    
    <entry>
        <title>Spin-down your USB HD and make it last longer </title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/XW-FCzQauno/Spin-down-your-USB-HD-and-make-it-last-longer" />
        <id>tag:blog.ivandemarino.me,2013-02-10:post:340001</id>
        <updated>2013-02-10T21:27:49Z</updated>
        <published>2013-02-10T21:27:49Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;I have built for myself a simple Media Center, based on &lt;a href="http://www.zotacusa.com/zbox-id41-plus.html"&gt;Zotac ZBOX ID41 Plus&lt;/a&gt;, &lt;a href="http://wiki.xbmc.org/index.php?title=XBMCbuntu"&gt;XBMC-Live&lt;/a&gt;, &lt;a href="http://www.transmissionbt.com/"&gt;Transmission&lt;/a&gt;, &lt;a href="http://flirc.tv/"&gt;Flirc&lt;/a&gt; and other useful stuff. The idea is having a low-energy consumption machine that I control with a remote. And it has to be always on.
&lt;/p&gt;
&lt;p&gt;One thing I was concerned about is how to deal with my external HD connected to it: I'm of course expecting those to eventually fail if they are always spinning.
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="http://www.colourbox.com/preview/2111168-646188-read-data-on-hard-disk-with-spinning-hard-disk.jpg" /&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;Well, a bit of scripting and cron can go a long way. Here is my solution.
&lt;/p&gt;

&lt;h3&gt;Step 1: dependencies&lt;/h3&gt;
&lt;p&gt;Just install &lt;a href="http://linux.die.net/man/8/sdparm"&gt;sdparm&lt;/a&gt; and you should be all set, at least on a "normal" Linux box where &lt;a href="http://en.wikipedia.org/wiki/Cron"&gt;Cron&lt;/a&gt; is already configured.
&lt;/p&gt;

&lt;h3&gt;Step 2: scripting &lt;code&gt;FTW&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Put a script like this somewhere in your system. I have it in my &lt;code&gt;~/bin&lt;/code&gt;:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# !/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Only ROOT can run this&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;$(id -u)&amp;quot;&lt;/span&gt; !&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; “This script must be run as root” 1&amp;gt;&amp;amp;2&lt;br /&gt;        &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;br /&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="nv"&gt;STATE_FILENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;state_&lt;span class="nv"&gt;$1&lt;/span&gt;.spindown&lt;br /&gt;&lt;span class="nv"&gt;PREV_STATE_FILENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prev_state_&lt;span class="nv"&gt;$1&lt;/span&gt;.spindown&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Get new state from diskstats&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;NEWstate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;cat /proc/diskstats | grep &lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEWstate&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;&amp;quot;$STATE_FILENAME&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# compare md5 sums&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;md5new&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;md5sum &lt;span class="nv"&gt;$STATE_FILENAME&lt;/span&gt; | sed &lt;span class="s1"&gt;&amp;#39;s/ .*//&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="nv"&gt;md5old&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;md5sum &lt;span class="nv"&gt;$PREV_STATE_FILENAME&lt;/span&gt; | sed &lt;span class="s1"&gt;&amp;#39;s/ .*//&amp;#39;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# if no changes, power down&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;$md5new&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;$md5old&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;; &lt;span class="k"&gt;then&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;        &lt;/span&gt;sdparm --flexible --command&lt;span class="o"&gt;=&lt;/span&gt;stop /dev/&lt;span class="nv"&gt;$1&lt;/span&gt; &amp;amp;&amp;gt;/dev/null&lt;br /&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Write current state to file&lt;/span&gt;&lt;br /&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$NEWstate&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;&amp;quot;$PREV_STATE_FILENAME&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;A very basic and simple one, isn't it?
   What it does is just probe &lt;code&gt;/proc/diskstats&lt;/code&gt; virtual file to get info about the recent activity of a disk. If it has not changed in the last 30 minutes, than it's time to use &lt;code&gt;sdparm&lt;/code&gt; to send a stop command &lt;code&gt;--command=stop&lt;/code&gt;. That's it.
&lt;/p&gt;

&lt;h3&gt;Step 3: Cron-it-up!&lt;/h3&gt;
&lt;p&gt;Add the following lines to your &lt;code&gt;/etc/crontab&lt;/code&gt;:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1
2
3
4
5&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;*/30 *   * * *   root   sh /home/xbmc/bin/spindown/spindown.sh sda&lt;br /&gt;*/30 *   * * *   root   sh /home/xbmc/bin/spindown/spindown.sh sdb&lt;br /&gt;*/30 *   * * *   root   sh /home/xbmc/bin/spindown/spindown.sh sdc&lt;br /&gt;*/30 *   * * *   root   sh /home/xbmc/bin/spindown/spindown.sh sdd&lt;br /&gt;*/30 *   * * *   root   sh /home/xbmc/bin/spindown/spindown.sh sde&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;The above lines execute the script against &lt;code&gt;sda&lt;/code&gt;, &lt;code&gt;sdb&lt;/code&gt;, &lt;code&gt;sdc&lt;/code&gt;, &lt;code&gt;sdd&lt;/code&gt; and &lt;code&gt;sde&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;That's it. I have been using this method for almost 2 years not, and  thought it might be helpful to others.
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/XW-FCzQauno" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2013/02/10/Spin-down-your-USB-HD-and-make-it-last-longer</feedburner:origLink></entry>
    
    <entry>
        <title>Finally, GhostDriver 1.0.0</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/sW8JxQaUww4/Finally-GhostDriver-1-0-0" />
        <id>tag:blog.ivandemarino.me,2013-01-29:post:339001</id>
        <updated>2013-01-29T16:25:52Z</updated>
        <published>2012-12-04T07:29:03Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;After ~10 months of work, I finally managed to push the ball forward enough to reach &lt;strong&gt;GhostDriver 1.0.0&lt;/strong&gt;.
   I won't lie: it does feel great. It always is to see so much effort mutate into an &lt;em&gt;achievement&lt;/em&gt;,
   even it is such only for me.
&lt;/p&gt;
&lt;p&gt;Before I go any further though, I owe a massive &lt;strong&gt;THANK-YOU&lt;/strong&gt; to the people that through contribution
   and / or issue reporting have helped me to build a &lt;em&gt;releasable&lt;/em&gt; 1.0.0. In particular to
   &lt;a href="http://jimevansmusic.blogspot.co.uk/"&gt;Jim Evans&lt;/a&gt;, an awesome guy and a bit of a
   mentor for me: you ROCK Jim, and I think that is true, &lt;em&gt;literally!&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="http://fc02.deviantart.net/fs71/i/2011/149/0/e/ghost_driver_by_swanee3-d3hkmjo.jpg" alt="Ghost Driver" width="600" /&gt;
   &lt;/div&gt;
&lt;/p&gt;

&lt;h2&gt;Explaining &lt;code&gt;1.0.0&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;In 1.0.0 I wanted to have the right amount of &lt;a href="http://code.google.com/p/selenium/wiki/JsonWireProtocol"&gt;Wire Protocol&lt;/a&gt;
   implemented, but still be able to deliver something stable before &lt;strong&gt;Christmas 2012&lt;/strong&gt;!
&lt;/p&gt;
&lt;p&gt;So, what's in GhostDriver 1.0.0 (&lt;a href="https://github.com/detro/ghostdriver/blob/master/CHANGELOG.md"&gt;changelog&lt;/a&gt;)?
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     Navigation
 &lt;/li&gt;

 &lt;li&gt;
     Page content extraction
 &lt;/li&gt;

 &lt;li&gt;
     Arbitrary JS execution
 &lt;/li&gt;

 &lt;li&gt;
     Window handling
 &lt;/li&gt;

 &lt;li&gt;
     Frame handling
 &lt;/li&gt;

 &lt;li&gt;
     Screen-shot generation
 &lt;/li&gt;

 &lt;li&gt;
     Cookies
 &lt;/li&gt;

 &lt;li&gt;
     Element Search, Localization &amp;amp; Manipulation
 &lt;/li&gt;

 &lt;li&gt;
     Mouse interaction (even though &lt;code&gt;doubeClick&lt;/code&gt; and &lt;code&gt;rightClick&lt;/code&gt; seems to be a bit flaky)
 &lt;/li&gt;

 &lt;li&gt;
     Keyboard interaction
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It's not the entire protocol yet, but it feels like a good start: I do think you can cover a lot of ground in your
   tests with those already.
&lt;/p&gt;
&lt;p&gt;To monitor progress, and to know in details what's there and what's not, check
   &lt;a href="https://docs.google.com/spreadsheet/ccc?key=0Am63grtxc7bDdGNqX1ZPX2VoZlE2ZHZhd09lNDkzbkE#gid=0"&gt;this spreadsheet out&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;You said "explaining"...&lt;/h3&gt;
&lt;p&gt;OK. So, GhostDriver is developed as a plain PhantomJS script that makes use of basically 2 PhantomJS built-in
   modules:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;code&gt;require("webserver")&lt;/code&gt;: to receive the Wire Protocol REST commands HTTP Requests
 &lt;/li&gt;

 &lt;li&gt;
     &lt;code&gt;require("webpage")&lt;/code&gt;: to execute those commands into Browser Windows (i.e. 1 &lt;code&gt;webpage&lt;/code&gt; corresponds to 1 &lt;code&gt;window&lt;/code&gt;)
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can download the source code from the repository
   (see &lt;a href="https://github.com/detro/ghostdriver/blob/master/README.md"&gt;README.md&lt;/a&gt;), and launch it with the following:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;phantomjs ghostdriver/src/main.js &lt;span class="o"&gt;[&lt;/span&gt;LOCAL_IP:&lt;span class="o"&gt;]&lt;/span&gt;PORT&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;This approach was and is &lt;strong&gt;for development only&lt;/strong&gt; though: GhostDriver target, since the beginning,
   was to embed the driver into PhantomJS - a feature demanded
   &lt;a href="http://code.google.com/p/phantomjs/issues/detail?id=49"&gt;since February 2011&lt;/a&gt;(!!!).
&lt;/p&gt;
&lt;p&gt;So, from next release of PhantomJS (&lt;strong&gt;1.8&lt;/strong&gt; should come just before Christmas) you will be able to do instead:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;phantomjs --webdriver&lt;span class="o"&gt;=[&lt;/span&gt;LOCAL_IP:&lt;span class="o"&gt;]&lt;/span&gt;PORT&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;without the need to download anything but your favourite &lt;em&gt;single-binary-headless-browser&lt;/em&gt;.
   If you are impatient though, just download latest PhantomJS &lt;code&gt;master&lt;/code&gt; branch, compile with &lt;code&gt;./build.sh&lt;/code&gt; and enjoy.
&lt;/p&gt;

&lt;h3&gt;Binding&lt;/h3&gt;
&lt;p&gt;To make it easier to get started, &lt;a href="https://github.com/lukeis"&gt;Luke Inman&lt;/a&gt;-&lt;a href="https://twitter.com/tunabum"&gt;Semerau&lt;/a&gt;,
   Jim Evans and I have provided binding classes that
   will make even easier to get up and running with PhantomJS/GhostDriver in your Selenium/WebDriver tests.
   &lt;a href="https://code.google.com/p/selenium/source/browse/#svn%2Ftrunk%2Fpy%2Fselenium%2Fwebdriver%2Fphantomjs"&gt;Luke is providing Python binding&lt;/a&gt;,
   &lt;a href="https://code.google.com/p/selenium/source/browse/#svn%2Ftrunk%2Fdotnet%2Fsrc%2FWebDriver%2FPhantomJS"&gt;Jim covers C#/.Net&lt;/a&gt;
   and &lt;a href="https://github.com/detro/ghostdriver/tree/master/binding/java/jars"&gt;I wrote the Java&lt;/a&gt; ones.
&lt;/p&gt;
&lt;p&gt;The next Selenium version is &lt;code&gt;2.27.0&lt;/code&gt;, and it's going to contain those bindings (hurray!). As I write this,
   &lt;a href="http://www.theautomatedtester.co.uk/"&gt;David Burns&lt;/a&gt; is
   &lt;a href="https://groups.google.com/forum/?fromgroups=#!topic/selenium-developers/0wFXuEHU2hs"&gt;taking matters into his hands&lt;/a&gt;
   to prepare the release.
&lt;/p&gt;
&lt;p&gt;But I'm sure you want to see some code. Here is a Java snippet:
&lt;/p&gt;
&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.openqa.selenium.phantomjs.PhantomJSDriver&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestPhantomJSDriver&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// prepare capabilities&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;Capabilities&lt;/span&gt; &lt;span class="n"&gt;caps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DesiredCapabilities&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJavascriptEnabled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;//&amp;lt; not really needed: JS enabled by default&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCapability&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;takesScreenshot&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;//&amp;lt; yeah, GhostDriver haz screenshotz!&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCapability&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;br /&gt;            &lt;span class="n"&gt;PhantomJSDriverService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PHANTOMJS_EXECUTABLE_PATH_PROPERTY&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class="s"&gt;&amp;quot;/path/to/your/phantomjs/binary/greater/than/1.7&amp;quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class="o"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Launch driver (will take care and ownership of the phantomjs process)&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;WebDriver&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PhantomJSDriver&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caps&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Load Google.com&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.google.com&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Locate the Search field on the Google page&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;WebElement&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findElement&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Type Cheese&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;strToSearchFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Cheese!&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendKeys&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strToSearchFor&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Submit form&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;submit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// Check results contains the term we searched for&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strToSearchFor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="c1"&gt;// done&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;quit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;br /&gt;    &lt;span class="o"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;

&lt;p&gt;It's also important to highlight that &lt;strong&gt;GhostDriver implements the standard WebDriver WireProtocol&lt;/strong&gt;.
   This means that you can connect to a running instance of PhantomJS in WebDriver mode by simply using any
   &lt;code&gt;RemoteWebDriver&lt;/code&gt; class available in your favourite language. No strict need to use those bindings.
&lt;/p&gt;

&lt;h2&gt;Where do I get it?&lt;/h2&gt;
&lt;p&gt;Because GhostDriver is now part of PhantomJS, you can get it in the next PhantomJS binary, stable release.
   It should be &lt;strong&gt;PhantomJS 1.8&lt;/strong&gt;, and should be out by the 21st of December (don't tell &lt;a href="http://ariya.ofilabs.com/"&gt;Ariya&lt;/a&gt;
   I told you that - it's still cooking :-) ).
&lt;/p&gt;
&lt;p&gt;In the meantime, as briefly mentioned above, you have to do a bit of leg work: check out latest PhantomJS
   &lt;code&gt;master&lt;/code&gt; branch (from either &lt;a href="https://github.com/ariya/phantomjs"&gt;Ariya's (official upstream)&lt;/a&gt; or
   &lt;a href="https://github.com/detro/phantomjs"&gt;my own (usually in sync with upstream)&lt;/a&gt;),
   and compile it (takes 30 minutes on average specs machine - much less if you have got &lt;em&gt;SSD&lt;/em&gt;).
&lt;/p&gt;
&lt;p&gt;The nice thing is that to build this you apply the same "set-up" required to compile any PhantomJS: nothing special
   is required. Just follow the instructions from &lt;a href="http://phantomjs.org/build.html"&gt;here&lt;/a&gt;
   if you have never compiled it before.
&lt;/p&gt;

&lt;h2&gt;After &lt;code&gt;1.0.0&lt;/code&gt;: what's next?&lt;/h2&gt;
&lt;p&gt;There is a lot left to do. To push for 1.0.0 I had to make compromises, particularly in the number of Wire Protocol
   commands I had to implement. Few key ones haven't made it, but work on them it's already started
   (mostly in my head for now).
&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;1.0.1&lt;/code&gt;: bug fixes&lt;/h3&gt;
&lt;p&gt;I plan to have a &lt;code&gt;1.0.1&lt;/code&gt; to address all the immediate issues. The work for this will be limited fixing bugs though.
   I already got a couple of issues / comments reported and I'll act on those.
&lt;/p&gt;
&lt;p&gt;So, don't expect this release to be anything BUT bug-fixes: new stuff has to go in &lt;em&gt;"at the right time"&lt;/em&gt; (see next).
&lt;/p&gt;
&lt;p&gt;A quick list of issues that will be address in this release:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/123"&gt;Issue #123&lt;/a&gt;:
Wait for potential "Page Load" when "Element.click()" is used
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/119"&gt;Issue #119&lt;/a&gt;:
Command &lt;code&gt;/shutdown&lt;/code&gt; arrives via &lt;code&gt;HTTP HEAD&lt;/code&gt; in some language bindings (by &lt;a href="https://github.com/jarib"&gt;Jari Bakken&lt;/a&gt;)
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/124"&gt;Issue #124&lt;/a&gt;:
Invalid response when checking element equality
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/126"&gt;Issue #126&lt;/a&gt;:
Crash on &lt;code&gt;get&lt;/code&gt; + &lt;code&gt;execute_async_script&lt;/code&gt;
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Track the work for &lt;code&gt;1.0.1&lt;/code&gt; &lt;a href="https://github.com/detro/ghostdriver/issues?labels=1.0.1&amp;amp;page=1&amp;amp;state=open"&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;1.1.0&lt;/code&gt;: new features&lt;/h3&gt;
&lt;p&gt;This is &lt;em&gt;"the right time"&lt;/em&gt; to add new features. This will be about pushing towards a full, complete WireProtocol
   implementation. So far I have picked the following from the issue tracker:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/108"&gt;Issue #108&lt;/a&gt;: "Timeouts default value should be INFINITE"
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/120"&gt;Issue #120&lt;/a&gt;:
Improve command line interface: support for just &lt;code&gt;--webdriver&lt;/code&gt; without parameters
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/121"&gt;Issue #121&lt;/a&gt;:
Better check for command line parameter: enforce &lt;code&gt;LOCAL_IP:PORT&lt;/code&gt; or &lt;code&gt;localhost:PORT&lt;/code&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/20"&gt;Issue #20&lt;/a&gt;: Implement support for JavaScript Alert/Prompt/Confirm
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/84"&gt;Issue #84&lt;/a&gt;:
Rewrite the Request Routing code to be more like &lt;a href="http://expressjs.com/"&gt;Node.js's Express&lt;/a&gt;
 &lt;/li&gt;

 &lt;li&gt;
     &lt;a href="https://github.com/detro/ghostdriver/issues/57"&gt;Issue #57&lt;/a&gt;: Implement "Drag &amp;amp; Drop" action builder
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Track the work for &lt;code&gt;1.1.0&lt;/code&gt; &lt;a href="https://github.com/detro/ghostdriver/issues?labels=1.1&amp;amp;page=1"&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;1.x&lt;/code&gt;: finishing up&lt;/h3&gt;
&lt;p&gt;Well, this is quite simple. I can't plan too much ahead, but the idea is to push toward 100% of the whole
   WireProtocol. Maybe putting on top of that some Mobile User Agent simulation, but that requires some thinking first.
&lt;/p&gt;

&lt;h2&gt;Anything else?&lt;/h2&gt;
&lt;p&gt;Developing a WebDriver has been quite a journey so far, and it's not yet finished.
   If you listen to some of the Selenium devs, apparently will never actually end, as issues, feature requests,
   criticism and pure simple &lt;em&gt;trolling&lt;/em&gt; should keep flowing. At least that should happen if this is successful.
&lt;/p&gt;
&lt;p&gt;That might turn out to be tiring (or a failure), but I don't hide that knowing this is something that
   few people actually want to use makes me a tiny bit proud of my self.
&lt;/p&gt;

&lt;h3&gt;Priorities&lt;/h3&gt;
&lt;p&gt;Before I go deep into another cycle of development though, my personal life is to regain some priority:
   &lt;strong&gt;I'm getting married in April 2013&lt;/strong&gt;. That, as you might expect, will take time and energy.
   So, if you want to contribute to a small Open Source project that has some potential to be awesome, please join me and
   the other few awesome souls that helped me so far. And this leads me to my last thoughts and conclusions...
&lt;/p&gt;

&lt;h3&gt;Lesson learned (still learning actually!)&lt;/h3&gt;
&lt;p&gt;As any small Open Source project, I need contributors. People that are willing to either write code, or kind enough
   to report issues in a &lt;strong&gt;proper and reproducible&lt;/strong&gt; manner.
   One thing I had to learn is that, if I want to keep this project going, I need to be very strict in what I allow
   myself to get involved into.
&lt;/p&gt;
&lt;p&gt;And, worst of all, while I got a bunch of guys really supportive of this work (I'm looking at you, Selenium-ers),
   there is always the kind of jerk that prefers to spend time telling you why you are going
   to fail, instead of trying to help you contributing improvements or fixes.
&lt;/p&gt;
&lt;p&gt;Those "encounters" taught me some very useful things:
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
     &lt;em&gt;Open Source it's not Democracy&lt;/em&gt;: You have to keep the ship sailing in the right direction
 &lt;/li&gt;

 &lt;li&gt;
     &lt;em&gt;Open Source it's a "doers" culture&lt;/em&gt;: ignore who talks and does nothing - embrace who makes things happen
 &lt;/li&gt;

 &lt;li&gt;
     &lt;em&gt;Lots of people ignore README files&lt;/em&gt;: they just don't read - but don't get too upset by it
 &lt;/li&gt;

 &lt;li&gt;
     &lt;em&gt;Kill unhelpful issues&lt;/em&gt;: they pollute the bug-tracker and lower morale, but reopen and discuss if the reporter "comes back to his senses"
 &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I have recently started to read &lt;a href="http://www.amazon.co.uk/Team-Geek-Software-Developers-Working/dp/1449302440"&gt;Team Geek&lt;/a&gt;, and it matches perfectly what I have experienced so far. Read it if you can!
&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;This post was long overdue, and it took me few days to finish it up. I'm sure I could add more details here, but it's now the 4th night in a row and I want to move on.
&lt;/p&gt;
&lt;p&gt;What else can I say? &lt;strong&gt;Just that I hope this to be the first of other, even better releases!&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;Happy Driving! :)
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/sW8JxQaUww4" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2012/12/04/Finally-GhostDriver-1-0-0</feedburner:origLink></entry>
    
    <entry>
        <title>GhostDriver, 90% and priorities</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/1T0tBB9lnbo/GhostDriver-90-and-priorities" />
        <id>tag:blog.ivandemarino.me,2012-10-23:post:338001</id>
        <updated>2012-10-23T22:41:38Z</updated>
        <published>2012-10-05T01:26:50Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;Last few weeks have been HECTIC to say the least. Work on &lt;a href="https://github.com/detro/ghostdriver"&gt;GhostDriver&lt;/a&gt; and &lt;a href="https://github.com/detro/phantomjs/tree/ghostdriver-dev"&gt;related PhantomJS improvements&lt;/a&gt; has been very intense.
&lt;/p&gt;
&lt;p&gt;We just shipped &lt;a href="http://ariya.ofilabs.com/2012/09/phantomjs-1-7-blazing-star.html"&gt;PhantomJS 1.7&lt;/a&gt;, and work for 1.8 is already started (check out the &lt;code&gt;ghostdriver-dev&lt;/code&gt; branch I linked above).
&lt;/p&gt;
&lt;p&gt;GhostDriver has reached almost 90% completion for 1.0, and the code is being &lt;strong&gt;hardened&lt;/strong&gt;, thanks also to the amazing work that &lt;a href="http://jimevansmusic.blogspot.co.uk/"&gt;Jim Evans&lt;/a&gt; is doing at spotting issues and, a lot of times, providing fixes. GhostDriver is getting better and better thanks to you Jim.
&lt;/p&gt;

&lt;h2&gt;Yes, but in short, what's left to do?&lt;/h2&gt;
&lt;p&gt;Based on &lt;a href="https://docs.google.com/spreadsheet/ccc?key=0Am63grtxc7bDdGNqX1ZPX2VoZlE2ZHZhd09lNDkzbkE"&gt;my plan&lt;/a&gt;, to release 1.0 I'm missing "only":
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Handling of &lt;code&gt;window.alert&lt;/code&gt;, &lt;code&gt;window.confirm&lt;/code&gt; and &lt;code&gt;window.prompt&lt;/code&gt;
 &lt;/li&gt;

 &lt;li&gt;
     Handling of &lt;code&gt;LocalStorage&lt;/code&gt; and &lt;code&gt;SessionStorage&lt;/code&gt;
 &lt;/li&gt;

 &lt;li&gt;
     Handling fo &lt;code&gt;/log&lt;/code&gt; commands
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recently though I have been thinking and discussing with others and I decided that I'd delay the support for those 3 things in favour of:
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Fix issues related to Mouse interaction
 &lt;/li&gt;

 &lt;li&gt;
     Integrate GhostDriver into PhantomJS itself (I need to prepare a plan with &lt;a href="ariya.ofilabs.com"&gt;Ariya&lt;/a&gt;)
 &lt;/li&gt;

 &lt;li&gt;
     Providing a Java Binding (Jim Evans already pushed a .Net binding into the Selenium codebase)
 &lt;/li&gt;

 &lt;li&gt;
     Code hardening
 &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;WHAAAAT? Are you crazy? No "alert()"?&lt;/h2&gt;
&lt;p&gt;Yeah, I know. While &lt;code&gt;LocalStorage&lt;/code&gt; can be seen as &lt;em&gt;nice-to-have&lt;/em&gt; features for &lt;code&gt;1.0&lt;/code&gt;, being able to interact with &lt;code&gt;alert()&lt;/code&gt; (and relata) is a big deal.
&lt;/p&gt;
&lt;p&gt;The issue there is that the current PhantomJS doesn't provide an easy way to implement those commands: while PhantomJS does provide support for &lt;code&gt;alert&lt;/code&gt;, &lt;code&gt;prompt&lt;/code&gt; and &lt;code&gt;confirm&lt;/code&gt; (I wrote them myself!),  it will probably require quite some work to "adapt" PhantomJS/GhostDriver to the way the WebDriver API work for those things.
&lt;/p&gt;
&lt;p&gt;In short: PhantomJS allows you to register a &lt;code&gt;onAlert/onConfirm/onPrompt&lt;/code&gt; callback to handle those events - WebDriver treats those as a "state" in which the Window is. Maybe I could write a never-returning callback? I don't know, it requires time to think about the best solution.
&lt;/p&gt;
&lt;p&gt;And that the point: I think I got no time now.
&lt;/p&gt;

&lt;h2&gt;The best thing I can do right now&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Time&lt;/strong&gt; is key here.
&lt;/p&gt;
&lt;p&gt;I think the best thing I can do right now for the &lt;strong&gt;PhantomJS WebDriver project future&lt;/strong&gt;, is to release a 1.0 version, with the hope it will receive enough &lt;em&gt;road test&lt;/em&gt;, so that 1.1 and later can be better, comprehensive, more &lt;em&gt;WebDriver-worthy&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;Ah, and did I mention that I'm moving to &lt;a href="http://corporate.blog.lovefilm.com/"&gt;Amazon LoveFilm&lt;/a&gt;? But that's for another post...
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/1T0tBB9lnbo" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2012/10/05/GhostDriver-90-and-priorities</feedburner:origLink></entry>
    
    <entry>
        <title>Look mummy, I'm 80% done!</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/mn9ZrR_9R3g/Look-mummy-I-m-80-done" />
        <id>tag:blog.ivandemarino.me,2012-08-13:post:337001</id>
        <updated>2012-08-13T19:58:10Z</updated>
        <published>2012-08-09T01:55:59Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;Let me give you a quick update about &lt;a href="https://github.com/detro/ghostdriver"&gt;GhostDriver&lt;/a&gt;, the &lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; WebDriver implementation.
&lt;/p&gt;
&lt;p&gt;Yes, it's &lt;strong&gt;80%&lt;/strong&gt; ready for prime time (bugs aside)!!!
&lt;/p&gt;
&lt;p&gt;How did I get from 40% to 80% so quickly? Because I decided that, for version 1.0, the commands that relate to the mobile web driver are out of scope. 1.1 or 1.2 will have them.
&lt;/p&gt;
&lt;p&gt;For details, I suggest you check out the &lt;a href="https://docs.google.com/spreadsheet/ccc?key=0Am63grtxc7bDdGNqX1ZPX2VoZlE2ZHZhd09lNDkzbkE"&gt;spreadsheet I'm using to track progress&lt;/a&gt; closely.
&lt;/p&gt;
&lt;p&gt;Some might call it "cheating". I call it "focusing".
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/mn9ZrR_9R3g" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2012/08/09/Look-mummy-I-m-80-done</feedburner:origLink></entry>
    
    <entry>
        <title>The Stupid Olympics</title>
        <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/BlogIvanDeMarino/~3/8dLom47ZV9k/The-Stupid-Olympics" />
        <id>tag:blog.ivandemarino.me,2012-08-01:post:335001</id>
        <updated>2012-08-01T17:02:08Z</updated>
        <published>2012-08-01T17:02:08Z</published>
        <author>
            <name>Ivan De Marino</name>
            <uri>http://blog.ivandemarino.me/</uri>
        </author>
        <content type="html">
            &lt;p&gt;I'm baffled on how stupid the British officials and politicians are. The entire show, is as bad in practice as it looks good on TV.
&lt;/p&gt;
&lt;p&gt;&lt;div class="img"&gt;
   &lt;img src="http://cdn.memegenerator.net/instances/400x/24097826.jpg" /&gt;
   &lt;/div&gt;
&lt;/p&gt;
&lt;ul&gt;
 &lt;li&gt;
     Business &lt;em&gt;starving&lt;/em&gt; for customers in Central London
 &lt;/li&gt;

 &lt;li&gt;
     No one has tickets: either because are too expensive or because buying tickets was a Olympic sport on it's own
 &lt;/li&gt;

 &lt;li&gt;
     Empty stations and entire city areas because of TfL &lt;em&gt;end-of-the-world-is-night&lt;/em&gt; emails
 &lt;/li&gt;

 &lt;li&gt;
     Trains, somehow, still managed to get fucked up and cancelled
 &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Was all this on purpose?
&lt;/p&gt;
        &lt;img src="http://feeds.feedburner.com/~r/BlogIvanDeMarino/~4/8dLom47ZV9k" height="1" width="1"/&gt;</content>
    <feedburner:origLink>http://blog.ivandemarino.me/2012/08/01/The-Stupid-Olympics</feedburner:origLink></entry>
    
</feed>
