zhaopuming / quickfast

Automatically exported from code.google.com/p/quickfast
Other
1 stars 0 forks source link

Nested sequence decoding error #68

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
QuickFAST fails to decode decimals (and maybe something else) in nested 
sequences, I've written a simple template xml and a program that demonstrates 
this.

The xml is:

<?xml version="1.0" encoding="UTF-8" ?>
<templates xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
    <template name="Test1Message" id="5000" xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
        <sequence name="Parties">
            <length name="NoParties" id="9998"/>
            <sequence name="Entries">
                <length name="NoEntries" id="9997"/>
                <decimal name="Price" id="80"><copy/></decimal>
            </sequence>
        </sequence>
    </template>
    <template name="Test2Message" id="4000" xmlns="http://www.fixprotocol.org/ns/fast/td/1.1">
        <sequence name="Entries">
            <length name="NoEntries" id="8997"/>
            <decimal name="Price" id="70"><copy/></decimal>
        </sequence>
    </template>
</templates>

And here's the program:

#include <Common/QuickFASTPch.h>
#include <Codecs/XMLTemplateParser.h>
#include <Codecs/DataDestinationString.h>
#include <Codecs/DataSourceString.h>
#include <Codecs/TemplateRegistry.h>
#include <Codecs/Decoder.h>
#include <Codecs/Encoder.h>
#include <Messages/FieldDecimal.h>
#include <Messages/FieldSequence.h>
#include <Messages/Sequence.h>
#include <Messages/FieldIdentity.h>
#include <Codecs/GenericMessageBuilder.h>
#include <Codecs/SingleMessageConsumer.h>

int main(int argc, char* argv[])
{
    std::ifstream is("test.xml", std::ios_base::binary | std::ios_base::in);

    QuickFAST::Codecs::TemplateRegistryPtr templateRegistry =
       QuickFAST::Codecs::XMLTemplateParser().parse(is);

    QuickFAST::Codecs::Encoder enc(templateRegistry);
    QuickFAST::Codecs::Decoder dec(templateRegistry);

    QuickFAST::Messages::FieldSetPtr msg(new QuickFAST::Messages::FieldSet(20));

    QuickFAST::Messages::FieldIdentityCPtr noParties(new QuickFAST::Messages::FieldIdentity("NoParties"));

    QuickFAST::Messages::SequencePtr parties(new QuickFAST::Messages::Sequence(noParties, 20));

    QuickFAST::Messages::FieldSetPtr p1(new QuickFAST::Messages::FieldSet(20));

    QuickFAST::Messages::FieldIdentityCPtr noEntries(new QuickFAST::Messages::FieldIdentity("NoEntries"));

    QuickFAST::Messages::SequencePtr entries(new QuickFAST::Messages::Sequence(noEntries, 20));

    QuickFAST::Messages::FieldSetPtr e1(new QuickFAST::Messages::FieldSet(20));

    e1->addField( QuickFAST::Messages::FieldIdentityCPtr(new QuickFAST::Messages::FieldIdentity("Price")),
                  QuickFAST::Messages::FieldDecimal::create(QuickFAST::Decimal(1, -1)) ); //(1, 0) is ok

    entries->addEntry(e1);
    entries->addEntry(e1);
    entries->addEntry(e1);

    p1->addField( QuickFAST::Messages::FieldIdentityCPtr(new QuickFAST::Messages::FieldIdentity("Entries")),
                  QuickFAST::Messages::FieldSequence::create(entries) );

    parties->addEntry(p1);
    parties->addEntry(p1);
    parties->addEntry(p1);

    msg->addField( QuickFAST::Messages::FieldIdentityCPtr(new QuickFAST::Messages::FieldIdentity("Parties")),
                   QuickFAST::Messages::FieldSequence::create(parties) );

    QuickFAST::Codecs::TemplateCPtr tpl;

    if (!enc.findTemplate("Test1Message", "", tpl))
    {
        std::cout << "template not found" << std::endl;
        return 1;
    }

    QuickFAST::Codecs::DataDestinationString dest;

    enc.encodeMessage(dest, tpl->getId(), *msg);

    std::cout << "encoded" << std::endl;

    QuickFAST::Codecs::DataSourceString src(dest.getValue());

    QuickFAST::Codecs::SingleMessageConsumer consumer;

    QuickFAST::Codecs::GenericMessageBuilder builder(consumer);

    try
    {
        dec.decodeMessage(src, builder);

        std::cout << "decoded" << std::endl;

        return 0;
    }
    catch (const std::exception& e)
    {
        std::cout << "error: " << e.what() << std::endl;

        return 1;
    }
}

That program supposed to encode a message and decode it without fault.
So, the expected output is:

encoded
decoded

But I get this instead:

encoded
error: [ERR U03] EOF while decoding presence map.

But, if I change QuickFAST::Decimal(1, -1) in the code above
to, say, QuickFAST::Decimal(1, 0), everything works well:

encoded
decoded

The problem seems to occur only in nested sequences, it doesn't occur in
topmost sequences, for example, the program below tests template "Test2Message":

#include <Common/QuickFASTPch.h>
#include <Codecs/XMLTemplateParser.h>
#include <Codecs/DataDestinationString.h>
#include <Codecs/DataSourceString.h>
#include <Codecs/TemplateRegistry.h>
#include <Codecs/Decoder.h>
#include <Codecs/Encoder.h>
#include <Messages/FieldDecimal.h>
#include <Messages/FieldSequence.h>
#include <Messages/Sequence.h>
#include <Messages/FieldIdentity.h>
#include <Codecs/GenericMessageBuilder.h>
#include <Codecs/SingleMessageConsumer.h>

int main(int argc, char* argv[])
{
    std::ifstream is("test.xml", std::ios_base::binary | std::ios_base::in);

    QuickFAST::Codecs::TemplateRegistryPtr templateRegistry =
       QuickFAST::Codecs::XMLTemplateParser().parse(is);

    QuickFAST::Codecs::Encoder enc(templateRegistry);
    QuickFAST::Codecs::Decoder dec(templateRegistry);

    QuickFAST::Messages::FieldSetPtr msg(new QuickFAST::Messages::FieldSet(20));

    QuickFAST::Messages::FieldIdentityCPtr noEntries(new QuickFAST::Messages::FieldIdentity("NoEntries"));

    QuickFAST::Messages::SequencePtr entries(new QuickFAST::Messages::Sequence(noEntries, 20));

    QuickFAST::Messages::FieldSetPtr e1(new QuickFAST::Messages::FieldSet(20));

    e1->addField( QuickFAST::Messages::FieldIdentityCPtr(new QuickFAST::Messages::FieldIdentity("Price")),
                  QuickFAST::Messages::FieldDecimal::create(QuickFAST::Decimal(1, -1)) );

    entries->addEntry(e1);
    entries->addEntry(e1);
    entries->addEntry(e1);

    msg->addField( QuickFAST::Messages::FieldIdentityCPtr(new QuickFAST::Messages::FieldIdentity("Entries")),
                   QuickFAST::Messages::FieldSequence::create(entries) );

    QuickFAST::Codecs::TemplateCPtr tpl;

    if (!enc.findTemplate("Test2Message", "", tpl))
    {
        std::cout << "template not found" << std::endl;
        return 1;
    }

    QuickFAST::Codecs::DataDestinationString dest;

    enc.encodeMessage(dest, tpl->getId(), *msg);

    std::cout << "encoded" << std::endl;

    QuickFAST::Codecs::DataSourceString src(dest.getValue());

    QuickFAST::Codecs::SingleMessageConsumer consumer;

    QuickFAST::Codecs::GenericMessageBuilder builder(consumer);

    try
    {
        dec.decodeMessage(src, builder);

        std::cout << "decoded" << std::endl;

        return 0;
    }
    catch (const std::exception& e)
    {
        std::cout << "error: " << e.what() << std::endl;

        return 1;
    }
}

And it works well, the output is:

encoded
decoded

I'm using QuickFAST 1.2 downloaded from here:

http://quickfast.googlecode.com/files/quickfast_lnx_src_1_2.tar.gz

uname -a = Linux ORION 2.6.31-22-generic-pae #65-Ubuntu SMP Thu Sep 16 16:02:41 
UTC 2010 i686 GNU/Linux

gcc --version = gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1

Original issue reported on code.google.com by shephm...@gmail.com on 5 Oct 2010 at 11:31

GoogleCodeExporter commented 9 years ago
Thanks for providing a test program.

Original comment by dale.wil...@gmail.com on 5 Oct 2010 at 3:02

GoogleCodeExporter commented 9 years ago
I modified your example into a new unit test:  testNestedSequences.  This test 
is in R448.

The test passes.  The problem has been fixed since version 1.2 was created.

Try pulling from the tip of the repository, please.

Dale

Original comment by dale.wil...@gmail.com on 5 Oct 2010 at 8:42

GoogleCodeExporter commented 9 years ago
[duplicate message.  code.google.com encountered an error in the previous 
message]

I converted the test program you provided into a new unit test: 
testNestedSequences which is now checked into subversion (R448)

The test passes.  The problem has been fixed since V1.2 was created.

Pulling the source from the tip of the repository should solve the problem you 
are seeing.

Original comment by dale.wil...@gmail.com on 5 Oct 2010 at 8:45