/*
 * vdr-podcatcher - A plugin for the Linux Video Disk Recorder
 * Copyright (c) 2006 Tobias Grimm <vdr@e-tobi.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: rssfeedparser_test.cc 3211 2006-04-14 21:01:37Z svntobi $
 *
 */

#include <sstream>
#include <libxml/xmlerror.h>
#include <cxxtest/TestSuite.h>
#include "rssfeedparser.h"
#include "feed.h"
#include "downloadcachemock.h"

using namespace std;

class XmlErrorOutputSuppressor
{
    public:
        static void xmlErrorFunc (void * ctx, const char * msg, ...) { }

        XmlErrorOutputSuppressor()
        {
            xmlSetGenericErrorFunc(NULL, xmlErrorFunc);
        }

        ~XmlErrorOutputSuppressor()
        {
            xmlSetGenericErrorFunc(NULL, NULL);
        }
};

class RssFeedParserTest: public CxxTest::TestSuite
{
    private:
        Feed* feed;
        RssFeedParser* parser;
        DownloadCacheMock downloadCache;

    private:
        string CreateXmlTag(string name, string value)
        {
            return "<" + name + ">" + value + "</" + name + ">";
        }

        string CreateRssFeed(string title, string items)
        {
            string result;

            result  = "<?xml version='1.0'?>";
            result += "<rss version='2.0'><channel>";
            result +=  CreateXmlTag("title", title);
            result +=  items;
            result += "</channel></rss>";

            return result;
        }

        string CreateRssItem(string title, string pubDate,
          string description, string enclosureUrl,
          string enclosureType)
        {
            string result;

            result  = "<item>";
            result += CreateXmlTag("title", title);
            result += CreateXmlTag("pubDate", pubDate);
            result += CreateXmlTag("description", description);
            if (enclosureUrl != "")
            {
              result += "<enclosure url='" + enclosureUrl +
                "' type='" + enclosureType + "'/>";
            }
            result += "</item>";

            return result;
        }

        void TestParse(RssFeedParser& parser, Feed& feed,
          int ExpectedNumberOfItems)
        {
            TS_ASSERT(parser.Parse(feed));
            TS_ASSERT_EQUALS(ExpectedNumberOfItems, feed.GetItems().size());
        }

    public:
        void setUp()
        {
            feed = new Feed("");
            parser = new RssFeedParser(downloadCache);
        }

        void tearDown()
        {
            delete parser;
            delete feed;
        }

        void TestParseNotExistingFile()
        {
            downloadCache.streamReturnedByCache = NULL;

            TS_ASSERT(!parser->Parse(*feed));
        }

        void TestParseInvalidXml()
        {
            XmlErrorOutputSuppressor xmlErrorOutputSuppressor;

            downloadCache.streamReturnedByCache = new stringstream(
              "<invalidXml>");

            TS_ASSERT(!parser->Parse(*feed));
        }

        void TestParseFeedWithoutItems()
        {
            downloadCache.streamReturnedByCache = new stringstream(
              CreateRssFeed("FooTitle", ""));

            TestParse(*parser, *feed, 0);
            TS_ASSERT_EQUALS("FooTitle", feed->GetTitle());
        }

        void TestParseSingleItem()
        {
            string item = CreateRssItem("ItemTitle", "3 Jun 2005 04:00:00 GMT",
              "ItemDescription", "", "");

            downloadCache.streamReturnedByCache = new stringstream(
              CreateRssFeed("FooTitle", item));

            TestParse(*parser, *feed, 1);
            TS_ASSERT_EQUALS("ItemTitle", feed->GetItems()[0].GetTitle());
            TS_ASSERT_EQUALS("ItemDescription",
              feed->GetItems()[0].GetDescription());
            TS_ASSERT_EQUALS("03.06.05",
              feed->GetItems()[0].GetDate().ToShortString());
            TS_ASSERT_EQUALS("", feed->GetItems()[0].GetMp3Url());
        }

        void TestParseTwoItems()
        {
            string item1 = CreateRssItem("ItemTitle1", "",  "", "", "");
            string item2 = CreateRssItem("ItemTitle2", "",  "", "", "");

            downloadCache.streamReturnedByCache = new stringstream(
              CreateRssFeed("FooTitle", item1 + item2));

            TestParse(*parser, *feed, 2);
            TS_ASSERT_EQUALS("ItemTitle1", feed->GetItems()[0].GetTitle());
            TS_ASSERT_EQUALS("ItemTitle2", feed->GetItems()[1].GetTitle());
        }

        void TestInvalidEnclosure()
        {
            string item = CreateRssItem("", "", "", "EnclosureUrl",
              "invalidType");

            downloadCache.streamReturnedByCache =
              new stringstream(CreateRssFeed("", item));

            TestParse(*parser, *feed, 1);
            TS_ASSERT_EQUALS("", feed->GetItems()[0].GetMp3Url());
        }

        void TestValidEnclosure()
        {
            string item = CreateRssItem("", "", "", "EnclosureUrl",
              "audio/mpeg");

            downloadCache.streamReturnedByCache =
              new stringstream(CreateRssFeed("", item));

            TestParse(*parser, *feed, 1);
            TS_ASSERT_EQUALS("EnclosureUrl", feed->GetItems()[0].GetMp3Url());
        }

        void TestHtmlStripping()
        {
            string item = CreateRssItem("", "", "<![CDATA[<br>test<br>]]>",
               "", "");

            downloadCache.streamReturnedByCache = new stringstream(
              CreateRssFeed("FooTitle", item));

            TestParse(*parser, *feed, 1);
            TS_ASSERT_EQUALS("test", feed->GetItems()[0].GetDescription());
        }
};
