/*
 * LinearStringTerminatingSymbolBWTTest.cpp
 *
 *  Created on: 17. 02. 2021
 *      Author: Martin Prokopic
 */

#include "catch2/catch.hpp"

#include <string/String.h>
#include <string/LinearStringTerminatingSymbolBWT.h>
#include <string/xml/LinearStringTerminatingSymbolBWT.h>
#include <factory/XmlDataFactory.hpp>

using string::LinearString;
using string::LinearStringTerminatingSymbolBWT;
using factory::XmlDataFactory;
using object::Object;
using alphabet::MinimalEndSymbol;

TEST_CASE ( "LinearStringTerminatingSymbolBWT", "[unit][string]" ) {

    SECTION ( "normal operation" ) {
        auto testcase = GENERATE( std::string ( "banana$" ), std::string ( "ban$ana" ), std::string ( "$" ));

        auto str = string::stringFrom ( testcase );
        INFO ( str );
        REQUIRE_NOTHROW ( LinearStringTerminatingSymbolBWT < char > ( '$', str ));
    }

    SECTION ( "throws CommonException if content doesn't contain terminating symbol" ) {
        auto testcase = GENERATE( std::string ( "banana" ), std::string ( "" ));

        auto str = string::stringFrom ( testcase );
        INFO ( str );
        REQUIRE_THROWS_AS ( LinearStringTerminatingSymbolBWT < char > ( '$', str ), exception::CommonException );
    }

    SECTION ( "throws CommonException if content contains multiple terminating symbols" ) {
        auto testcase = GENERATE( std::string ( "banana$$" ), std::string ( "b$anana$" ), std::string ( "$$" ));

        auto str = string::stringFrom ( testcase );
        INFO ( str );
        REQUIRE_THROWS_AS ( LinearStringTerminatingSymbolBWT < char > ( '$', str ), exception::CommonException );
    }

    SECTION ( "can be serialized and deserialized through xmlApi" ) {
        auto testcase1 = LinearStringTerminatingSymbolBWT < char > ( '$', string::stringFrom ( "banana$" ));

        LinearString < Object > str = string::stringFrom (
                ext::vector < Object >{ Object ( 'a' ), Object ( 'b' ), MinimalEndSymbol::instance < Object > ( ) } );
        auto testcase2 = LinearStringTerminatingSymbolBWT < Object > ( MinimalEndSymbol::instance < Object > ( ), str );

        auto testcase1Normalized = core::normalize<LinearStringTerminatingSymbolBWT<char>>::eval(std::move(testcase1));

        std::string xml;

        xml = XmlDataFactory::toString ( testcase1Normalized );
        INFO( xml );
        REQUIRE ( static_cast<LinearStringTerminatingSymbolBWT < Object >>(XmlDataFactory::fromString ( xml )) ==
                  testcase1Normalized );

        xml = XmlDataFactory::toString ( testcase2 );
        INFO( xml );
        REQUIRE ( static_cast<LinearStringTerminatingSymbolBWT < Object >>(XmlDataFactory::fromString ( xml )) ==
                  testcase2 );
    }

}