//CUPPA:include=+
#include "../src/MiX/SAX_Parser.h"
//CUPPA:include=-
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestAssert.h>

//CUPPA:namespace=+
//CUPPA:namespace=-
#define T(str) MiX::XMLString<char>( str )

class SAX_ParserTest : public CppUnit::TestFixture , 
		       public MiX::SAX_EventHandler<char>{
  CPPUNIT_TEST_SUITE(SAX_ParserTest);
//CUPPA:suite=+
  CPPUNIT_TEST(testParseBuffer);
  CPPUNIT_TEST(testParseStream);
//CUPPA:suite=-
  CPPUNIT_TEST_SUITE_END();
private:

  // your stuff...
  enum EventType{
    Event_xml,
    Event_start,
    Event_end,
    Event_text,
    Event_comment,
    Event_attr,
  };
  struct Event{
    EventType type;
    std::string name;
    std::string val;
  };
  static const Event seq_[];
  static const char data_[];
  int seq_n_;

public:

  virtual void setUp() { /* initialize */ }
  virtual void tearDown() { /* terminate */ }

//CUPPA:decl=+
  void testParseBuffer() {
    MiX::SAX_Parser<char> parser;
    parser.setEventHandler(this);
    parser.setIgnoreSpace(false);
    seq_n_ = 0;
    parser.parse(data_);
  }
  
  void testParseStream() {
    MiX::SAX_Parser<char> parser;
    parser.setEventHandler(this);
    parser.setIgnoreSpace(false);
    seq_n_ = 0;
    std::istringstream ss(data_);
    parser.parse(ss);
  }
//CUPPA:decl=-
  void onXMLDeclaration(attrmap_type attr){
    CPPUNIT_ASSERT_EQUAL(seq_[seq_n_].type,Event_xml);
    ++seq_n_;
    attrmap_type::iterator it = attr.begin();
    attrmap_type::iterator last = attr.end();
    for( ; it!=last ; ++it){
      CPPUNIT_ASSERT_EQUAL( seq_[seq_n_].type,Event_attr );
      CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].name), it->first );
      CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].val), it->second );
      ++seq_n_;
    }
  }
  void onStart(string_type name,attrmap_type attr){
    CPPUNIT_ASSERT_EQUAL(seq_[seq_n_].type,Event_start);
    CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].name), name );
    ++seq_n_;
    attrmap_type::iterator it = attr.begin();
    attrmap_type::iterator last = attr.end();
    for( ; it!=last ; ++it){
      CPPUNIT_ASSERT_EQUAL( seq_[seq_n_].type, Event_attr );
      CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].name), it->first );
      CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].val), it->second );
      ++seq_n_;
    }
  }
  void onEnd(string_type name){
    CPPUNIT_ASSERT_EQUAL(seq_[seq_n_].type,Event_end);
    CPPUNIT_ASSERT_EQUAL( name, T(seq_[seq_n_].name) );
    ++seq_n_;
  }
  void onText(string_type text){
    CPPUNIT_ASSERT_EQUAL(seq_[seq_n_].type,Event_text);
    CPPUNIT_ASSERT_EQUAL( T(seq_[seq_n_].val), text );
    ++seq_n_;
  }
  void onComment(string_type text){
    CPPUNIT_ASSERT_EQUAL(seq_[seq_n_].type,Event_comment);
    CPPUNIT_ASSERT_EQUAL( text, T(seq_[seq_n_].val) );
    ++seq_n_;
  }
};

//CUPPA:impl=+
const SAX_ParserTest::Event SAX_ParserTest::seq_[] =  {
  { Event_xml , "" , "" },
  { Event_attr , "version" , "1.0" },
  { Event_attr , "encoding" , "UTF-8" },
  { Event_comment , "" , " test start " },
  { Event_start , "TestSuite" , "" } ,
  { Event_attr , "name" , "SAX_ParserTest" } ,
  { Event_comment , "" , " This is test \ncomment. " },
  { Event_start , "TestCase" , "" } ,
  { Event_attr , "name" , "testParse" } ,
  { Event_end , "TestCase" , "" } ,
  { Event_text , "" , "This is "} ,
  { Event_start , "b" , "" } ,
  { Event_text , "" , "test"} ,
  { Event_end , "b" , "" } ,
  { Event_text , "" , " text."} ,
  { Event_end , "TestSuite" , "" } ,
};

const char SAX_ParserTest::data_[] = {
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  "<!-- test start -->"
  "<TestSuite name=\"SAX_ParserTest\">"
  "<!-- This is test \ncomment. -->"
  "<TestCase name=\"testParse\"/>"
  "This is <b>test</b> text."
  "</TestSuite>"
};

//CUPPA:impl=-

CPPUNIT_TEST_SUITE_REGISTRATION(SAX_ParserTest);
