//***************************************************************************
//* Copyright (c) 2019 Saint Petersburg State University
//* All Rights Reserved
//* See file LICENSE for details.
//***************************************************************************

#include "sequence/rtseq.hpp"
#include "sequence/sequence.hpp"
#include "sequence/nucl.hpp"
#include <string>
#include <gtest/gtest.h>

typedef unsigned long long ull;

TEST( RtSeq, Selector ) {
    EXPECT_EQ('G', nucl(RtSeq(10, "ACGTACGTAC")[2]));
    EXPECT_EQ('G', nucl(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC")[2]));
    EXPECT_EQ('G', nucl(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC")[16]));
    EXPECT_EQ('T', nucl(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC")[17]));
    EXPECT_EQ('A', nucl(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC")[18]));
    EXPECT_EQ('C', nucl(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC")[19]));

    EXPECT_EQ('C', nucl(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACCT")[15]));
    EXPECT_EQ('G', nucl(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACCT")[16]));
    EXPECT_EQ('C', nucl(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACCT")[31]));
    EXPECT_EQ('G', nucl(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACCT")[32]));
    EXPECT_EQ('T', nucl(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACCT")[63]));

    EXPECT_EQ('C', nucl(RtSeq(32, "ACGTACGTACACGTACGTACACGTACGTACAC")[15]));
    EXPECT_EQ('G', nucl(RtSeq(32, "ACGTACGTACACGTACGTACACGTACGTACAC")[16]));
    EXPECT_EQ('C', nucl(RtSeq(32, "ACGTACGTACACGTACGTACACGTACGTACAC")[31]));

    EXPECT_EQ('C', nucl(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACC")[15]));
    EXPECT_EQ('G', nucl(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACC")[16]));
    EXPECT_EQ('C', nucl(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACC")[32]));

}

TEST( RtSeq, ShiftLeft ) {
    EXPECT_EQ(RtSeq(5, "ACACA"), (RtSeq(5, "CACAC") << dignucl('A')));
    EXPECT_EQ(RtSeq(5, "ACACC"), (RtSeq(5, "CACAC") << dignucl('C')));
    EXPECT_EQ(RtSeq(5, "ACACG"), (RtSeq(5, "CACAC") << dignucl('G')));
    EXPECT_EQ(RtSeq(5, "ACACT"), (RtSeq(5, "CACAC") << dignucl('T')));

    RtSeq s(10, "ACGTACGTAC");
    EXPECT_EQ(RtSeq(10, "CGTACGTACA"), (s << dignucl('A')));
    EXPECT_EQ(RtSeq(10, "CGTACGTACC"), (s << dignucl('C')));
    EXPECT_EQ(RtSeq(10, "CGTACGTACG"), (s << dignucl('G')));
    EXPECT_EQ(RtSeq(10, "CGTACGTACT"), (s << dignucl('T')));

    RtSeq s2(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACA"), (s2 << dignucl('A')));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACC"), (s2 << dignucl('C')));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACG"), (s2 << dignucl('G')));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACT"), (s2 << dignucl('T')));

    RtSeq s2b(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGA"), (s2b << dignucl('A')));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGC"), (s2b << dignucl('C')));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGG"), (s2b << dignucl('G')));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGT"), (s2b << dignucl('T')));

    RtSeq s3(32, "ACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACA"), (s3 << dignucl('A')));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACC"), (s3 << dignucl('C')));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACG"), (s3 << dignucl('G')));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACT"), s3 << dignucl('T'));

    RtSeq s4(33, "TACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACA"), (s4 << dignucl('A')));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACC"), (s4 << dignucl('C')));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACG"), (s4 << dignucl('G')));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACT"), s4 << dignucl('T'));
}


TEST( RtSeq, ShiftLeftThis ) {
    RtSeq s0(5, "CACAC");
    s0 <<= 'A';
    EXPECT_EQ(RtSeq(5, "ACACA"), s0);
    s0 <<= 'C';
    EXPECT_EQ(RtSeq(5, "CACAC"), s0);
    s0 <<= 'G';
    EXPECT_EQ(RtSeq(5, "ACACG"), s0);
    s0 <<= 'T';
    EXPECT_EQ(RtSeq(5, "CACGT"), s0);

    size_t l;
    RtSeq s(10, "ACGTACGTAC");
    l = 10;
    s <<= 'A';
    EXPECT_EQ(RtSeq(l, "CGTACGTACA"), s);
    s <<= 'C';
    EXPECT_EQ(RtSeq(l, "GTACGTACAC"), s);
    s <<= 'G';
    EXPECT_EQ(RtSeq(l, "TACGTACACG"), s);
    s <<= 'T';
    EXPECT_EQ(RtSeq(l, "ACGTACACGT"), s);

    RtSeq s2(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    l = 60;
    s2 <<= 'A';
    EXPECT_EQ(RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACA"), s2);
    s2 <<= 'C';
    EXPECT_EQ(RtSeq(l, "GTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACAC"), s2);
    s2 <<= 'G';
    EXPECT_EQ(RtSeq(l, "TACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACG"), s2);
    s2 <<= 'T';
    EXPECT_EQ(RtSeq(l, "ACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGT"), s2);

    RtSeq s2b(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    l = 64;
    s2b <<= 'A';
    EXPECT_EQ(RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGA"), s2b);
    s2b <<= 'C';
    EXPECT_EQ(RtSeq(l, "GTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGAC"), s2b);
    s2b <<= 'G';
    EXPECT_EQ(RtSeq(l, "TACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGACG"), s2b);
    s2b <<= 'T';
    EXPECT_EQ(RtSeq(l, "ACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGACGT"), s2b);

    RtSeq s3(32, "ACGTACGTACACGTACGTACACGTACGTACAC");
    l = 32;
    s3 <<= 'C';
    EXPECT_EQ(RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACC"), s3);
    s3 <<= 'T';
    EXPECT_EQ(RtSeq(l, "GTACGTACACGTACGTACACGTACGTACACCT"), s3);
    s3 <<= 'A';
    EXPECT_EQ(RtSeq(l, "TACGTACACGTACGTACACGTACGTACACCTA"), s3);
    s3 <<= 'G';
    EXPECT_EQ(RtSeq(l, "ACGTACACGTACGTACACGTACGTACACCTAG"), s3);

    RtSeq s4(33, "TACGTACGTACACGTACGTACACGTACGTACAC");
    l = 33;
    s4 <<= 'C';
    EXPECT_EQ(RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACACC"), s4);
    s4 <<= 'T';
    EXPECT_EQ(RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACCT"), s4);
    s4 <<= 'A';
    EXPECT_EQ(RtSeq(l, "GTACGTACACGTACGTACACGTACGTACACCTA"), s4);
    s4 <<= 'G';
    EXPECT_EQ(RtSeq(l, "TACGTACACGTACGTACACGTACGTACACCTAG"), s4);
}


TEST( RtSeq, ShiftRight ) {
    EXPECT_EQ(RtSeq(5, "ACACA"), (RtSeq(5, "CACAC") >> dignucl('A')));
    EXPECT_EQ(RtSeq(5, "CCACA"), (RtSeq(5, "CACAC") >> dignucl('C')));
    EXPECT_EQ(RtSeq(5, "GCACA"), (RtSeq(5, "CACAC") >> dignucl('G')));
    EXPECT_EQ(RtSeq(5, "TCACA"), (RtSeq(5, "CACAC") >> dignucl('T')));

    RtSeq s(10, "ACGTACGTAC");
    EXPECT_EQ(RtSeq(10, "AACGTACGTA"), (s >> dignucl('A')));
    EXPECT_EQ(RtSeq(10, "CACGTACGTA"), (s >> dignucl('C')));
    EXPECT_EQ(RtSeq(10, "GACGTACGTA"), (s >> dignucl('G')));
    EXPECT_EQ(RtSeq(10, "TACGTACGTA"), (s >> dignucl('T')));

    RtSeq s2(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ(RtSeq(60, "AACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), (s2 >> dignucl('A')));
    EXPECT_EQ(RtSeq(60, "CACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), (s2 >> dignucl('C')));
    EXPECT_EQ(RtSeq(60, "GACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), (s2 >> dignucl('G')));
    EXPECT_EQ(RtSeq(60, "TACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), (s2 >> dignucl('T')));

    RtSeq s2b(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ(RtSeq(64, "AACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), (s2b >> dignucl('A')));
    EXPECT_EQ(RtSeq(64, "CACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), (s2b >> dignucl('C')));
    EXPECT_EQ(RtSeq(64, "GACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), (s2b >> dignucl('G')));
    EXPECT_EQ(RtSeq(64, "TACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), (s2b >> dignucl('T')));

    RtSeq s3(32, "ACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(32, "AACGTACGTACACGTACGTACACGTACGTACA"), (s3 >> dignucl('A')));
    EXPECT_EQ(RtSeq(32, "CACGTACGTACACGTACGTACACGTACGTACA"), (s3 >> dignucl('C')));
    EXPECT_EQ(RtSeq(32, "GACGTACGTACACGTACGTACACGTACGTACA"), (s3 >> dignucl('G')));
    EXPECT_EQ(RtSeq(32, "TACGTACGTACACGTACGTACACGTACGTACA"), (s3 >> dignucl('T')));

    RtSeq s4(33, "ACGTACGTACACGTACGTACACGTACGTACACT");
    EXPECT_EQ(RtSeq(33, "AACGTACGTACACGTACGTACACGTACGTACAC"), (s4 >> dignucl('A')));
    EXPECT_EQ(RtSeq(33, "CACGTACGTACACGTACGTACACGTACGTACAC"), (s4 >> dignucl('C')));
    EXPECT_EQ(RtSeq(33, "GACGTACGTACACGTACGTACACGTACGTACAC"), (s4 >> dignucl('G')));
    EXPECT_EQ(RtSeq(33, "TACGTACGTACACGTACGTACACGTACGTACAC"), (s4 >> dignucl('T')));
}


TEST( RtSeq, ShiftRightThis ) {
    size_t l;
    RtSeq s(5, "CACAC");
    l = 5;
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACACA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACAC"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACA"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCAC"), s);


    l = 9;
    s = RtSeq(l, "CGTACGTAC");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACGTACGTA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACGTACGT"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACGTACG"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCACGTAC"), s);

    l = 59;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGT"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACG"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTAC"), s);

    l = 63;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCG"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACC"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), s);


    l = 31;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACAC");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTAC"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACGTACGTACACGTACGTACACGTACGTA"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCACGTACGTACACGTACGTACACGTACGT"), s);

    l = 32;
    s = RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACAC");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "AACGTACGTACACGTACGTACACGTACGTACA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CAACGTACGTACACGTACGTACACGTACGTAC"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCAACGTACGTACACGTACGTACACGTACGTA"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCAACGTACGTACACGTACGTACACGTACGT"), s);

    l = 33;
    s = RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTACAC");
    s >>= ('A');
    EXPECT_EQ(RtSeq(l, "ACACGTACGTACACGTACGTACACGTACGTACA"), s);
    s >>= ('C');
    EXPECT_EQ(RtSeq(l, "CACACGTACGTACACGTACGTACACGTACGTAC"), s);
    s >>= ('G');
    EXPECT_EQ(RtSeq(l, "GCACACGTACGTACACGTACGTACACGTACGTA"), s);
    s >>= ('T');
    EXPECT_EQ(RtSeq(l, "TGCACACGTACGTACACGTACGTACACGTACGT"), s);
}



TEST( RtSeq, Str ) {
    RtSeq s(10, "ACGTACGTAC");
    EXPECT_EQ("ACGTACGTAC", s.str());
    RtSeq s2(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ("ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC", s2.str());
    RtSeq s2b(64, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG", s2b.str());
    RtSeq s3(32, "TCGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ("TCGTACGTACACGTACGTACACGTACGTACAC", s3.str());
    RtSeq s4(33, "ACGTACGTACACGTACGTACACGTACGTACACT");
    EXPECT_EQ("ACGTACGTACACGTACGTACACGTACGTACACT", s4.str());
}

TEST( RtSeq, HeadAndTail ) {
    size_t l;

    l = 5;
    RtSeq s(l, "GCATC");
    EXPECT_EQ(RtSeq(l - 1, "CATC"), RtSeq(l - 1, s, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "GCAT"), RtSeq(l - 1, s)); // head

    l = 10;
    RtSeq s1(l, "CCGTACGTAC");
    EXPECT_EQ(RtSeq(l - 1, "CGTACGTAC"), RtSeq(l - 1, s1, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "CCGTACGTA"), RtSeq(l - 1, s1)); // head

    l = 60;
    RtSeq s2(l, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ(RtSeq(l - 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), RtSeq(l - 1, s2, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTA"), RtSeq(l - 1, s2)); // head

    l = 64;
    RtSeq s2b(l, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ(RtSeq(l - 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), RtSeq(l - 1, s2b, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGC"), RtSeq(l - 1, s2b)); // head

    l = 32;
    RtSeq s3(l, "TCGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(l - 1, "CGTACGTACACGTACGTACACGTACGTACAC"), RtSeq(l - 1, s3, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "TCGTACGTACACGTACGTACACGTACGTACA"), RtSeq(l - 1, s3)); // head

    l = 33;
    RtSeq s4(l, "GCGTACGTACACGTACGTACACGTACGTACACT");
    EXPECT_EQ(RtSeq(l - 1, "CGTACGTACACGTACGTACACGTACGTACACT"), RtSeq(l - 1, s4, 1)); // tail
    EXPECT_EQ(RtSeq(l - 1, "GCGTACGTACACGTACGTACACGTACGTACAC"), RtSeq(l - 1, s4)); // head
}

TEST( RtSeq, FromBiggerRtSeq ) {
    RtSeq s(64, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ("CCGTA", RtSeq(5, s).str());
    EXPECT_EQ("CCGTACGTAC", RtSeq(10, s).str());
    EXPECT_EQ("CCGTACGTACACGTAC", RtSeq(16, s).str());
    EXPECT_EQ("CCGTACGTACACGTACG", RtSeq(17, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACAC", RtSeq(32, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACG", RtSeq(33, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC", RtSeq(60, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG", RtSeq(64, s).str());
}

TEST( RtSeq, FromSeq ) {
    Seq<5> s("CGTAC");
    Seq<10> s1("ACGTACGTAC");
    Seq<16> s2("CCCCGTACGTACGTAC");
    Seq<32> s3("ACGTACGTACACGTACGTACACGTACGTACAC");
    Seq<33> s4("GACGTACGTACACGTACGTACACGTACGTACAC");
    Seq<60> s5("ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    Seq<64> s6("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");

    EXPECT_EQ(RtSeq(s, true).str(), s.str());
    EXPECT_EQ(RtSeq(s1, true).str(), s1.str());
    EXPECT_EQ(RtSeq(s2, true).str(), s2.str());
    EXPECT_EQ(RtSeq(s3, true).str(), s3.str());
    EXPECT_EQ(RtSeq(s4, true).str(), s4.str());
    EXPECT_EQ(RtSeq(s5, true).str(), s5.str());
    EXPECT_EQ(RtSeq(s6, true).str(), s6.str());
}

TEST( RtSeq, ToSeq ) {
    Seq<5> s("CGTAC");
    Seq<10> s1("ACGTACGTAC");
    Seq<16> s2("CCCCGTACGTACGTAC");
    Seq<32> s3("ACGTACGTACACGTACGTACACGTACGTACAC");
    Seq<33> s4("GACGTACGTACACGTACGTACACGTACGTACAC");
    Seq<60> s5("ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    Seq<64> s6("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");

    EXPECT_EQ(RtSeq(5, "CGTAC").get_seq<5>(), s);
    EXPECT_EQ(RtSeq(10, "ACGTACGTAC").get_seq<10>(), s1);
    EXPECT_EQ(RtSeq(16, "CCCCGTACGTACGTAC").get_seq<16>(), s2);
    EXPECT_EQ(RtSeq(32, "ACGTACGTACACGTACGTACACGTACGTACAC").get_seq<32>(), s3);
    EXPECT_EQ(RtSeq(33, "GACGTACGTACACGTACGTACACGTACGTACAC").get_seq<33>(), s4);
    EXPECT_EQ(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC").get_seq<60>(), s5);
    EXPECT_EQ(RtSeq(64, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG").get_seq<64>(), s6);

}

TEST( RtSeq, FromType ) {
    Sequence s("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ("CCGTA", RtSeq(5, s).str());
    EXPECT_EQ("CCGTACGTAC", RtSeq(10, s).str());
    EXPECT_EQ("CCGTACGTACACGTAC", RtSeq(16, s).str());
    EXPECT_EQ("CCGTACGTACACGTACG", RtSeq(17, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACAC", RtSeq(32, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACG", RtSeq(33, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC", RtSeq(60, s).str());
    EXPECT_EQ("CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG", RtSeq(64, s).str());

    EXPECT_EQ("GTA", RtSeq(3, s, 2).str());
    EXPECT_EQ("GTACGTACAC", RtSeq(10, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGT", RtSeq(16, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGTA", RtSeq(17, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGTACACGTACGTACACGT", RtSeq(32, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGTACACGTACGTACACGTA", RtSeq(33, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC", RtSeq(58, s, 2).str());
    EXPECT_EQ("GTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG", RtSeq(62, s, 2).str());
}

TEST( RtSeq, PushBack ) {
    EXPECT_EQ(RtSeq(6, "CACACA"), (RtSeq(5, "CACAC").pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(6, "CACACC"), (RtSeq(5, "CACAC").pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(6, "CACACG"), (RtSeq(5, "CACAC").pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(6, "CACACT"), (RtSeq(5, "CACAC").pushBack(dignucl('T'))));

    RtSeq s(9, "CGTACGTAC");
    EXPECT_EQ(RtSeq(10, "CGTACGTACA"), (s.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(10, "CGTACGTACC"), (s.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(10, "CGTACGTACG"), (s.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(10, "CGTACGTACT"), (s.pushBack(dignucl('T'))));

    RtSeq s2(59, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACA"), (s2.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACC"), (s2.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACG"), (s2.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(60, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACT"), (s2.pushBack(dignucl('T'))));

    RtSeq s2b(63, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGA"), (s2b.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGC"), (s2b.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGG"), (s2b.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(64, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGT"), (s2b.pushBack(dignucl('T'))));

    RtSeq s3(31, "CGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACA"), (s3.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACC"), (s3.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACG"), (s3.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(32, "CGTACGTACACGTACGTACACGTACGTACACT"), (s3.pushBack(dignucl('T'))));

    RtSeq s4(32, "ACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACA"), (s4.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACC"), (s4.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACG"), (s4.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(33, "ACGTACGTACACGTACGTACACGTACGTACACT"), (s4.pushBack(dignucl('T'))));

    RtSeq s5(33, "CACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(34, "CACGTACGTACACGTACGTACACGTACGTACACA"), (s5.pushBack(dignucl('A'))));
    EXPECT_EQ(RtSeq(34, "CACGTACGTACACGTACGTACACGTACGTACACC"), (s5.pushBack(dignucl('C'))));
    EXPECT_EQ(RtSeq(34, "CACGTACGTACACGTACGTACACGTACGTACACG"), (s5.pushBack(dignucl('G'))));
    EXPECT_EQ(RtSeq(34, "CACGTACGTACACGTACGTACACGTACGTACACT"), (s5.pushBack(dignucl('T'))));
}


TEST( RtSeq, PushBackThis ) {
    size_t l;
    RtSeq s(5, "CACAC");
    l = 5;
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CACACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "CACACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "CACACACGT"), s);


    l = 9;
    s = RtSeq(l, "CGTACGTAC");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CGTACGTACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "CGTACGTACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "CGTACGTACACGT"), s);

    l = 59;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGT"), s);

    l = 63;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGA"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGC"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGG"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCGT"), s);


    l = 31;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACAC");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CGTACGTACACGTACGTACACGTACGTACACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CGTACGTACACGTACGTACACGTACGTACACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "CGTACGTACACGTACGTACACGTACGTACACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "CGTACGTACACGTACGTACACGTACGTACACACGT"), s);

    l = 32;
    s = RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACAC");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACGTACGTACACGTACGTACACGTACGTACACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "ACGTACGTACACGTACGTACACGTACGTACACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "ACGTACGTACACGTACGTACACGTACGTACACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "ACGTACGTACACGTACGTACACGTACGTACACACGT"), s);

    l = 33;
    s = RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTACAC");
    s.pushBackThis('A');
    EXPECT_EQ(RtSeq(l + 1, "CACGTACGTACACGTACGTACACGTACGTACACA"), s);
    s.pushBackThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACGTACGTACACGTACGTACACGTACGTACACAC"), s);
    s.pushBackThis('G');
    EXPECT_EQ(RtSeq(l + 3, "CACGTACGTACACGTACGTACACGTACGTACACACG"), s);
    s.pushBackThis('T');
    EXPECT_EQ(RtSeq(l + 4, "CACGTACGTACACGTACGTACACGTACGTACACACGT"), s);
}


TEST( RtSeq, PushFront ) {
    EXPECT_EQ(RtSeq(6, "ACACAC"), (RtSeq(5, "CACAC").pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(6, "CCACAC"), (RtSeq(5, "CACAC").pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(6, "GCACAC"), (RtSeq(5, "CACAC").pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(6, "TCACAC"), (RtSeq(5, "CACAC").pushFront(dignucl('T'))));

    RtSeq s(9, "CGTACGTAC");
    EXPECT_EQ(RtSeq(10, "ACGTACGTAC"), (s.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(10, "CCGTACGTAC"), (s.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(10, "GCGTACGTAC"), (s.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(10, "TCGTACGTAC"), (s.pushFront(dignucl('T'))));

    RtSeq s2(59, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ(RtSeq(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), (s2.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(60, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), (s2.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(60, "GCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), (s2.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(60, "TCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), (s2.pushFront(dignucl('T'))));

    RtSeq s2b(63, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    EXPECT_EQ(RtSeq(64, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), (s2b.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(64, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), (s2b.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(64, "GCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), (s2b.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(64, "TCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), (s2b.pushFront(dignucl('T'))));

    RtSeq s3(31, "CGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(32, "ACGTACGTACACGTACGTACACGTACGTACAC"), (s3.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(32, "CCGTACGTACACGTACGTACACGTACGTACAC"), (s3.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(32, "GCGTACGTACACGTACGTACACGTACGTACAC"), (s3.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(32, "TCGTACGTACACGTACGTACACGTACGTACAC"), (s3.pushFront(dignucl('T'))));

    RtSeq s4(32, "ACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(33, "AACGTACGTACACGTACGTACACGTACGTACAC"), (s4.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(33, "CACGTACGTACACGTACGTACACGTACGTACAC"), (s4.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(33, "GACGTACGTACACGTACGTACACGTACGTACAC"), (s4.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(33, "TACGTACGTACACGTACGTACACGTACGTACAC"), (s4.pushFront(dignucl('T'))));

    RtSeq s5(33, "CACGTACGTACACGTACGTACACGTACGTACAC");
    EXPECT_EQ(RtSeq(34, "ACACGTACGTACACGTACGTACACGTACGTACAC"), (s5.pushFront(dignucl('A'))));
    EXPECT_EQ(RtSeq(34, "CCACGTACGTACACGTACGTACACGTACGTACAC"), (s5.pushFront(dignucl('C'))));
    EXPECT_EQ(RtSeq(34, "GCACGTACGTACACGTACGTACACGTACGTACAC"), (s5.pushFront(dignucl('G'))));
    EXPECT_EQ(RtSeq(34, "TCACGTACGTACACGTACGTACACGTACGTACAC"), (s5.pushFront(dignucl('T'))));
}


TEST( RtSeq, PushFrontThis ) {
    size_t l;
    RtSeq s(5, "CACAC");
    l = 5;
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACACAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACACAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCACACAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCACACAC"), s);


    l = 9;
    s = RtSeq(l, "CGTACGTAC");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACGTACGTAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACGTACGTAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCACGTACGTAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCACGTACGTAC"), s);

    l = 59;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC"), s);

    l = 63;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 1, "CCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 1, "GCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), s);
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG");
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 1, "TCGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACCGCG"), s);


    l = 31;
    s = RtSeq(l, "CGTACGTACACGTACGTACACGTACGTACAC");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCACGTACGTACACGTACGTACACGTACGTACAC"), s);

    l = 32;
    s = RtSeq(l, "ACGTACGTACACGTACGTACACGTACGTACAC");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "AACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CAACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCAACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCAACGTACGTACACGTACGTACACGTACGTACAC"), s);

    l = 33;
    s = RtSeq(l, "CACGTACGTACACGTACGTACACGTACGTACAC");
    s.pushFrontThis('A');
    EXPECT_EQ(RtSeq(l + 1, "ACACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('C');
    EXPECT_EQ(RtSeq(l + 2, "CACACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('G');
    EXPECT_EQ(RtSeq(l + 3, "GCACACGTACGTACACGTACGTACACGTACGTACAC"), s);
    s.pushFrontThis('T');
    EXPECT_EQ(RtSeq(l + 4, "TGCACACGTACGTACACGTACGTACACGTACGTACAC"), s);
}

TEST( RtSeq, Null ) {
    RtSeq s(0,"");
    EXPECT_EQ("", s.str());
}


TEST( RtSeq, AddSymbolForNullValue ) {
    RtSeq s1(1, "G");
    RtSeq s2 = (s1 << 'A');
    RtSeq s3(1, "A");
    EXPECT_EQ(s3, s2);
}


TEST( RtSeq, Complex ) {
    Sequence s1("ACAAA");
    Sequence s2("CAAAC");
    EXPECT_EQ((!(RtSeq(4, !s1))).str(), RtSeq(4, s2).str());
    EXPECT_EQ(!(RtSeq(4, !s1)), RtSeq(4, s2));
}

TEST( RtSeq, FromCharArray ) {
    std::string s = "ACGTACGTAC";
    EXPECT_EQ("ACGTACGTAC", RtSeq(10, s.c_str()).str());
}

TEST( RtSeq, ReverseComplement ) {
    RtSeq s(10, "ACGTACGTAC");
    EXPECT_EQ("GTACGTACGT", (!s).str());
    RtSeq s1(9, "CGTACGTAC");
    EXPECT_EQ("GTACGTACG", (!s1).str());
    RtSeq s2(60, "ACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ("GTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGT", (!s2).str());
    RtSeq s2b(64, "TGCAACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTACACGTACGTAC");
    EXPECT_EQ("GTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGTGTACGTACGTTGCA", (!s2b).str());
    RtSeq s3(32, "CGTACGTACACGTACGTACACGTACGTACACG");
    EXPECT_EQ("CGTGTACGTACGTGTACGTACGTGTACGTACG", (!s3).str());
    RtSeq s4(33, "ACGTACGTACACGTACGTACACGTACGTACACG");
    EXPECT_EQ("CGTGTACGTACGTGTACGTACGTGTACGTACGT", (!s4).str());
}

TEST( RtSeq, 16 ) {
    RtSeq s(16, "AAAAAAAAAAAAAAAA");
    EXPECT_EQ(s << 'C', RtSeq(16, "AAAAAAAAAAAAAAAC"));
}

TEST( RtSeq, 16_2 ) {
    RtSeq s(16, "TTTTTTTTTTTTTTTT");
    EXPECT_EQ(RtSeq(16, "TTTTTTTTTTTTTTTA"), s << 'A');
}

TEST( RtSeq, FirstLast ) {
    RtSeq s1(7, "ACGTACT");
    EXPECT_EQ(0, s1.first());
    EXPECT_EQ(3, s1.last());
    RtSeq s2(7, "TTTTTTT");
    EXPECT_EQ(3, s2.first());
    EXPECT_EQ(3, s2.last());
}
