<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Object Mentor Blog: Some C++ Fixtures for FitNesse.slim</title>
    <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description></description>
    <item>
      <title>Some C++ Fixtures for FitNesse.slim</title>
      <description>&lt;p&gt;I continue working on these. I was stuck in the airport for 5 hours. Between that and the actual flight, I managed to create three different test examples against a C++ RpnCalculator. Each example uses a different kind of fixture. I had a request from @lrojas to publish some results on the blog. So this is that, however these are in progress and rough.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m still trying different forms to figure out what I like the best.&lt;/p&gt;


	&lt;p&gt;By the way, that lastValue stuff in the fixtures has to do with the fact that all of the hook methods return a char* but I&amp;#8217;m responsible for cleaning up after myself.&lt;/p&gt;


&lt;h2&gt;A Decision Table&lt;/h2&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;!|ExecuteBinaryOperator    |
|lhs|rhs|operator|expected?|
|3  |4  |-       |-1       |
|5  |6  |*       |30       |&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;And Its Fixture Code&lt;/h2&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;quot;RpnCalculator.h&amp;quot;
#include &amp;quot;OperationFactory.h&amp;quot;
#include &amp;quot;Fixtures.h&amp;quot;
#include &amp;quot;SlimUtils.h&amp;quot;

struct ExecuteBinaryOperator {
    ExecuteBinaryOperator() {
        lastValue[0] = 0;
    }

    int execute() {
        RpnCalculator calculator(factory);
        calculator.enterNumber(lhs);
        calculator.enterNumber(rhs);
        calculator.executeOperator(op);
        return calculator.getX();
    }

    static ExecuteBinaryOperator* From(void *fixtureStorage) {
        return reinterpret_cast&amp;lt;ExecuteBinaryOperator*&amp;gt;(fixtureStorage);
    }

    OperationFactory factory;
    int lhs;
    int rhs;
    std::string op;
    char lastValue[32];
};

extern &amp;quot;C&amp;quot; {
void* ExecuteBinaryOperator_Create(StatementExecutor* errorHandler, SlimList* args) {
    return new ExecuteBinaryOperator;
}

void ExecuteBinaryOperator_Destroy(void* self) {
    delete ExecuteBinaryOperator::From(self);
}

static char* setLhs(void* fixture, SlimList* args) {
    ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture);
    self-&amp;gt;lhs = getFirstInt(args);
    return self-&amp;gt;lastValue;
}

static char* setRhs(void* fixture, SlimList* args) {
    ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture);
    self-&amp;gt;rhs = getFirstInt(args);
    return self-&amp;gt;lastValue;
}

static char* setOperator(void *fixture, SlimList* args) {
    ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture);
    self-&amp;gt;op = getFirstString(args);
    return self-&amp;gt;lastValue;
}
static char* expected(void* fixture, SlimList* args) {
    ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture);
    int result = self-&amp;gt;execute();
    snprintf(self-&amp;gt;lastValue, sizeof(self-&amp;gt;lastValue), &amp;quot;%d&amp;quot;, result);
    return self-&amp;gt;lastValue;
}

SLIM_CREATE_FIXTURE(ExecuteBinaryOperator)
    SLIM_FUNCTION(setLhs)
    SLIM_FUNCTION(setRhs)
    SLIM_FUNCTION(setOperator)
    SLIM_FUNCTION(expected)
SLIM_END

}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
There&amp;#8217;s a bit of duplication. I&amp;#8217;ve been experimenting with pointers to member functions and template functions to make it better. I really should be using lambdas, but I&amp;#8217;m not there yet. I have them available in some form since I&amp;#8217;m using gcc 4.5. I simply compile with the option -sdd=c++0x. Even so, I&amp;#8217;m not quite ready to do that.

&lt;h2&gt;A Script Table&lt;/h2&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;!|script           |ProgramTheCalculator                   |
|startProgramCalled|primeFactorsOfSum                      |
|addOperation      |sum                                    |
|addOperation      |primeFactors                           |
|saveProgram                                               |
|enter             |4                                      |
|enter             |13                                     |
|enter             |7                                      |
|execute           |primeFactorsOfSum                      |
|check             |stackHas|3|then|2|then|2|then|2|is|true|&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;And Its Fixture Code&lt;/h2&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;quot;RpnCalculator.h&amp;quot;
#include &amp;quot;OperationFactory.h&amp;quot;
#include &amp;quot;SlimUtils.h&amp;quot;
#include &amp;quot;SlimList.h&amp;quot;
#include &amp;quot;Fixtures.h&amp;quot;

struct ProgramTheCalculator {
    ProgramTheCalculator() : calculator(factory) {
    }

    static ProgramTheCalculator* From(void *fixtureStorage) {
        return reinterpret_cast&amp;lt;ProgramTheCalculator*&amp;gt;(fixtureStorage);
    }

    OperationFactory factory;
    RpnCalculator calculator;
};

extern &amp;quot;C&amp;quot; {

void* ProgramTheCalculator_Create(StatementExecutor* errorHandler, SlimList* args) {
    return new ProgramTheCalculator;
}

void ProgramTheCalculator_Destroy(void *fixture) {
    delete ProgramTheCalculator::From(fixture);
}

static char* startProgramCalled(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    self-&amp;gt;calculator.createProgramNamed(getFirstString(args));
    return remove_const(&amp;quot;&amp;quot;);
}

static char* addOperation(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    self-&amp;gt;calculator.addOperation(getFirstString(args));
    return remove_const(&amp;quot;&amp;quot;);
}

static char* saveProgram(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    self-&amp;gt;calculator.saveProgram();
    return remove_const(&amp;quot;&amp;quot;);
}

static char* enter(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    self-&amp;gt;calculator.enterNumber(getFirstInt(args));
    return remove_const(&amp;quot;&amp;quot;);
}

static char* execute(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    self-&amp;gt;calculator.executeOperator(getFirstString(args));
    return remove_const(&amp;quot;&amp;quot;);
}

static char* stackHasThenThenThenIs(void *fixture, SlimList *args) {
    auto *self = ProgramTheCalculator::From(fixture);
    for(int i = 0; i &amp;lt; 4; ++i) {
            if(self-&amp;gt;calculator.getX() != getIntAt(args, i))
                return remove_const(&amp;quot;false&amp;quot;);
            self-&amp;gt;calculator.executeOperator(&amp;quot;drop&amp;quot;);
    }

      return remove_const(&amp;quot;true&amp;quot;);
}

SLIM_CREATE_FIXTURE(ProgramTheCalculator)
    SLIM_FUNCTION(startProgramCalled)
    SLIM_FUNCTION(addOperation)
    SLIM_FUNCTION(saveProgram)
    SLIM_FUNCTION(enter)
    SLIM_FUNCTION(execute)
    SLIM_FUNCTION(stackHasThenThenThenIs)
SLIM_END

}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
This one is a bit more regular. I am using the updated auto keyword in this code. The fixture is just holding the calculator and its OperationFactory (not my preferred name, but that&amp;#8217;s what students wanted to call things like +, -, etc, operations not operators).

&lt;h2&gt;The Dreaded Query Table&lt;/h2&gt;
It&amp;#8217;s a bit of a pain to produce query results. So much so, I wrote a simple library in Java to make it easier. I can create a well-formed query result from a single object or a list of objects and even do basic transforms (in names and in paths to data). I started using the jakarta bean utils, but my use was so simple (2 methods), I ripped out that library and just hand-wrote the methods I needed. It was not a case of &amp;#8220;not invented here syndrom.&amp;#8221; I started by using the library, and I had tests. I didn&amp;#8217;t like the size of the library relative to how much I was using it, so I just got rid of it.

	&lt;p&gt;Well here I am working C++ and I felt compelled to make it easier work with query results in C++.&lt;/p&gt;


First the FitNesse table, then the fixture and finally the support  class. I have tests for it as well, I&amp;#8217;m not going to show those, however.
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;!|Query: SingleCharacterNameOperators|
|op                                  |
|+                                   |
|*                                   |
|/                                   |
|!                                   |
|-                                   |&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;And Its Fixture Code&lt;/h2&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;string&amp;gt;
#include &amp;lt;memory&amp;gt;
#include &amp;quot;RpnCalculator.h&amp;quot;
#include &amp;quot;OperationFactory.h&amp;quot;
#include &amp;quot;Fixtures.h&amp;quot;
#include &amp;quot;SlimUtils.h&amp;quot;
#include &amp;quot;QueryResultAccumulator.h&amp;quot;

struct SingleCharacterNameOperators {
    OperationFactory factory;
    RpnCalculator calculator;

    SingleCharacterNameOperators() :
        calculator(factory), result(0) {
    }

    ~SingleCharacterNameOperators() {
        delete result;
    }
    static SingleCharacterNameOperators* From(void *fixtureStorage) {
        return reinterpret_cast&amp;lt;SingleCharacterNameOperators*&amp;gt; (fixtureStorage);
    }

    void resetResult(char *newResult) {
        delete result;
        result = newResult;
    }

    void conditionallyAddOperatorNamed(const std::string &amp;amp;name) {
        if (name.size() == 1) {
            accumulator.addFieldNamedWithValue(&amp;quot;op&amp;quot;, name);
            accumulator.finishCurrentObject();
        }
    }

    void buildResult() {
        v_string names = calculator.allOperatorNames();
        buildResult(names);
    }

    void buildResult(v_string &amp;amp;names) {
        for (v_string::iterator iter = names.begin(); iter != names.end(); ++iter)
            conditionallyAddOperatorNamed(*iter);

        resetResult(accumulator.produceFinalResults());
    }

    QueryResultAccumulator accumulator;
    char *result;
};

extern &amp;quot;C&amp;quot; {
void* SingleCharacterNameOperators_Create(StatementExecutor* errorHandler,
        SlimList* args) {
    return new SingleCharacterNameOperators;
}

void SingleCharacterNameOperators_Destroy(void *fixture) {
    delete SingleCharacterNameOperators::From(fixture);
}

static char* query(void *fixture, SlimList *args) {
    auto *self = SingleCharacterNameOperators::From(fixture);
    self-&amp;gt;buildResult();
    return self-&amp;gt;result;
}

SLIM_CREATE_FIXTURE(SingleCharacterNameOperators)
    SLIM_FUNCTION(query)SLIM_END
SLIM_END&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;And the Helper Class&lt;/h2&gt;
&lt;b&gt;QueryResultAccumulator.h&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;#pragma once
#ifndef QUERYRESULTACCUMULATOR_H_
#define QUERYRESULTACCUMULATOR_H_

class SlimList;
#include &amp;lt;vector&amp;gt;
#include &amp;lt;string&amp;gt;
class QueryResultAccumulator {
public:
    typedef std::vector&amp;lt;SlimList*&amp;gt; v_SlimList;
    typedef v_SlimList::iterator iterator;

    QueryResultAccumulator();
    virtual ~QueryResultAccumulator();

    void finishCurrentObject();
    void addFieldNamedWithValue(const std::string &amp;amp;name, const std::string &amp;amp;value);
    char *produceFinalResults();

private:
    SlimList* allocate();
    void releaseAll();
    void setInitialConditions();

private:
    v_SlimList created;
    SlimList *list;
    SlimList *currentObject;
    int lastFieldCount;
    int currentFieldCount;
    char *result;

private:
    QueryResultAccumulator(const QueryResultAccumulator&amp;amp;);
    QueryResultAccumulator&amp;amp; operator=(const QueryResultAccumulator&amp;amp;);
};

#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I know there are too many fields. The counts help with validating correct usage. I also wrote it so one instance could be re-used and I tried to make sure it was in a &amp;#8220;ready to receive fields&amp;#8221; state when necessary. In any case, this error checking helped find a defect I introduced while refactoring.&lt;/p&gt;


&lt;b&gt;QueryResultAccumulator.cpp&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;#include &amp;quot;QueryResultAccumulator.h&amp;quot;
#include &amp;quot;DifferentFieldCountsInObjects.h&amp;quot;
#include &amp;quot;InvalidStateException.h&amp;quot;

extern &amp;quot;C&amp;quot; {
#include &amp;quot;SlimList.h&amp;quot;
#include &amp;quot;SlimListSerializer.h&amp;quot;
}

QueryResultAccumulator::QueryResultAccumulator() : result(0) {
    setInitialConditions();
}

QueryResultAccumulator::~QueryResultAccumulator() {
    releaseAll();
    SlimList_Release(result);
}

void QueryResultAccumulator::setInitialConditions() {
    releaseAll();
    list = allocate();
    currentObject = allocate();
    lastFieldCount = -1;
    currentFieldCount = -1;
}

SlimList* QueryResultAccumulator::allocate() {
    SlimList *list = SlimList_Create();
    created.push_back(list);
    return list;
}

void QueryResultAccumulator::releaseAll() {
    for (iterator i = created.begin(); i != created.end(); ++i)
        SlimList_Destroy(*i);
    created.clear();
}

void QueryResultAccumulator::finishCurrentObject() {
    if(lastFieldCount &amp;gt;= 0 &amp;amp;&amp;amp; lastFieldCount != currentFieldCount)
        throw DifferentFieldCountsInObjects(lastFieldCount, currentFieldCount);

    SlimList_AddList(list, currentObject);
    currentObject = allocate();

    lastFieldCount = currentFieldCount;
    currentFieldCount = -1;
}

void QueryResultAccumulator::addFieldNamedWithValue(const std::string &amp;amp;name, const std::string &amp;amp;value) {
    SlimList *fieldList = allocate();
    SlimList_AddString(fieldList, name.c_str());
    SlimList_AddString(fieldList, value.c_str());
    SlimList_AddList(currentObject, fieldList);
    ++currentFieldCount;
}

char* QueryResultAccumulator::produceFinalResults() {
    if(currentFieldCount != -1)
        throw InvalidStateException(&amp;quot;Current object not written&amp;quot;);

    SlimList_Release(result);
    result = SlimList_Serialize(list);
    setInitialConditions();
    return result;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

Note, this code uses a method I added to the cslim library:
&lt;b&gt;SlimListSerializer.h &amp;#8211; in include/CSlim&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;void SlimList_Release(char *serializedResults);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;b&gt;SlimListSerializer.c &amp;#8211; in src/CSlim&lt;/b&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;void SlimList_Release(char *serializedResults)
{
  if(serializedResults)
    free(serializedResults);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;I needed to add these methods due to a false-positive memory leak indicated when using CppUTest to test this code. That&amp;#8217;s another blog.&lt;/p&gt;</description>
      <pubDate>Thu, 22 Jul 2010 00:32:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:63a89994-cb84-4422-b3c8-5ac5e7f53331</guid>
      <author>Brett Schuchert</author>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim</link>
      <category>Schuchert's Scattered Synapses </category>
      <category>c</category>
      <category>FitNesse</category>
      <category>cslim</category>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by jenniferthomos2</title>
      <description>&lt;p&gt;How to convert AVI to iPad with best &lt;a href="http://www.bestipadconverter.com/" rel="nofollow"&gt; iPad Video Converter &lt;/a&gt; &amp;#8211; AVI to iPad
&lt;a href="http://www.bestipadconverter.com/guide/avi-to-ipad-converter.html" rel="nofollow"&gt; Best AVI to iPad Converter &lt;/a&gt; a professional iPad converter to convert avi files into iPad mp4 format, of course it can easily convert almost 100 kinds of videos to iPad for enjoying. The input format includes AVI, AMV, MKV, FLV, MTS, M2TS, MOD, H.264/AVC, RMVB, HD TS, HD MOV, WMV HD, etc.
Best &lt;a href="http://www.bestipadconverter.com/guide/avi-to-ipad-converter.html" rel="nofollow"&gt; AVI to iPad Converter &lt;/a&gt; allows users to enjoy videos with the large and high-resolution screen freely with your iPad. There are many powerful editing functions such as effect, trim, crop, add watermark, merge and so on.
RECOMMENDED: For Mac Users, you can try &lt;a href="http://www.bestipadconverter.com/mac-ipad-converter/" rel="nofollow"&gt; iPad Converter for Mac &lt;/a&gt; Version!
&lt;a href="http://www.bestipadconverter.com/guide/flv-to-ipad-converter.html" rel="nofollow"&gt; FLV to iPad Converter &lt;/a&gt; 
&lt;a href="http://www.bestipadconverter.com/guide/divx-to-ipad-converter.html" rel="nofollow"&gt; DivX to iPad Converter &lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 06 Sep 2010 01:54:22 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:81307d81-c2a1-4746-9344-333ba935f288</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-24310</link>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by pop110</title>
      <description>&lt;p&gt;Happy to see your blog as it is just what I&#8217;ve looking for and excited to read all the posts. I am looking forward to another great article from you. After skimming through your website&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://lakesidehomesearch.com" rel="nofollow"&gt;Lakeside Home Search&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 01 Sep 2010 06:21:28 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:2ca2dd25-3340-4d33-86c6-d97b84d27f9f</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-23588</link>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by supplynflshop</title>
      <description>&lt;p&gt;good post and thanks
&lt;a href="http://www.supplynflshop.com" rel="nofollow"&gt;http://www.supplynflshop.com&lt;/a&gt; cheap nfl jerseys&lt;/p&gt;</description>
      <pubDate>Tue, 31 Aug 2010 21:18:27 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:dbb1ffcf-b143-4818-8c57-acaec2218d3d</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-23380</link>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by pop122</title>
      <description>&lt;p&gt;I found this is an informative and interesting post so i think so it is very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this article.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://leucadia-realestate.com" rel="nofollow"&gt;Leucadia Real Estate&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 22 Aug 2010 16:08:55 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:657cdcd5-adf6-4cd5-993a-54d1ac778c5a</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-21431</link>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by pop122</title>
      <description>&lt;p&gt;I agree all these are really good content thank you for sharing&amp;#8230;.....&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://missionhillshomesearch.com" rel="nofollow"&gt;Mission Hills Real Estate&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 14 Aug 2010 13:02:40 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:3491a0f4-06e9-49ad-9cc2-7314d8d400d7</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-19978</link>
    </item>
    <item>
      <title>"Some C++ Fixtures for FitNesse.slim" by buy fat burner</title>
      <description>&lt;p&gt;I`m a novice in work with C++. I hope i will help me, great article!&lt;/p&gt;</description>
      <pubDate>Sun, 08 Aug 2010 08:49:24 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:b9bff6d4-bd1d-481d-9d8c-f27849f50b21</guid>
      <link>http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim#comment-19080</link>
    </item>
  </channel>
</rss>
