TEST(IupacAlignmentTests, BasicTest)
{
    PairwiseAlignment* a;
    a = AlignAffineIupac("GATTTT", "GMTTT");
    ASSERT_EQ("GATTTT", a->Target());
    ASSERT_EQ("GM-TTT", a->Query());
    delete a;

    a = AlignAffineIupac("TTTTAG", "TTTMG");
    ASSERT_EQ("TTTTAG", a->Target());
    ASSERT_EQ("-TTTMG", a->Query());
    delete a;
}
TEST(PairwiseAlignmentTests, GlobalAlignmentTests)
{
    PairwiseAlignment* a = Align("GATT", "GATT");
    EXPECT_FLOAT_EQ(1.0, a->Accuracy());
    EXPECT_EQ("GATT", a->Target());
    EXPECT_EQ("GATT", a->Query());
    EXPECT_EQ("MMMM", a->Transcript());
    delete a;

    a = Align("GATT", "GAT");
    EXPECT_FLOAT_EQ(0.75, a->Accuracy());
    EXPECT_EQ("GATT", a->Target());
    EXPECT_EQ("GA-T", a->Query());
    EXPECT_EQ("MMDM", a->Transcript());
    delete a;

    a = Align("GATTACA", "TT");
    EXPECT_EQ("GATTACA", a->Target());
    EXPECT_EQ("--TT---", a->Query());
    EXPECT_FLOAT_EQ(2./7, a->Accuracy());
    delete a;
}
TEST(AffineAlignmentTests, BasicTests)
{
    PairwiseAlignment* a = AlignWithAffineGapPenalty("ATT", "ATT");
    EXPECT_EQ("ATT", a->Target());
    EXPECT_EQ("ATT", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("AT", "ATT");
    EXPECT_EQ("A-T", a->Target());
    EXPECT_EQ("ATT", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("GA", "GAT");
    EXPECT_EQ("GA-", a->Target());
    EXPECT_EQ("GAT", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("GAT", "GA");
    EXPECT_EQ("GAT", a->Target());
    EXPECT_EQ("GA-", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("GA", "TGA");
    EXPECT_EQ("-GA", a->Target());
    EXPECT_EQ("TGA", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("TGA", "GA");
    EXPECT_EQ("TGA", a->Target());
    EXPECT_EQ("-GA", a->Query());
    delete a;

    a = AlignWithAffineGapPenalty("GATTACA", "GATTTACA");
    EXPECT_EQ("GA-TTACA", a->Target());
    EXPECT_EQ("GATTTACA", a->Query());
    delete a;
}
TEST(PairwiseAlignmentTests, JustifyTest)
{
    // deletion
    {
        PairwiseAlignment a = PairwiseAlignment("AAAAAA", "AAA-AA");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("-AAAAA", a.Query());
        EXPECT_EQ("DMMMMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("AAAAA-", a.Query());
        EXPECT_EQ("MMMMMD", a.Transcript());
    }

    // insertion
    {
        PairwiseAlignment a = PairwiseAlignment("A-AAAA", "AAAAAA");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("-AAAAA", a.Target());
        EXPECT_EQ("AAAAAA", a.Query());
        EXPECT_EQ("IMMMMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("AAAAA-", a.Target());
        EXPECT_EQ("AAAAAA", a.Query());
        EXPECT_EQ("MMMMMI", a.Transcript());
    }

    // interruption in homopolymer
    {
        PairwiseAlignment a = PairwiseAlignment("GATTTACA", "GAGT-ACA");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("GATTTACA", a.Target());
        EXPECT_EQ("GAG-TACA", a.Query());
        EXPECT_EQ("MMRDMMMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("GATTTACA", a.Target());
        EXPECT_EQ("GAGT-ACA", a.Query());
        EXPECT_EQ("MMRMDMMM", a.Transcript());
    }

    // double bases, adjacent
    {
        PairwiseAlignment a = PairwiseAlignment("AAAAAA", "AAA--A");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("--AAAA", a.Query());
        EXPECT_EQ("DDMMMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("AAAA--", a.Query());
        EXPECT_EQ("MMMMDD", a.Transcript());
    }

    // double bases, separated
    {
        PairwiseAlignment a = PairwiseAlignment("AAAAAA", "A-AA-A");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("--AAAA", a.Query());
        EXPECT_EQ("DDMMMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("AAAAAA", a.Target());
        EXPECT_EQ("AAAA--", a.Query());
        EXPECT_EQ("MMMMDD", a.Transcript());
    }

    // intervening insertion
    {
        PairwiseAlignment a = PairwiseAlignment("A----A", "AATAAA");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("----AA", a.Target());
        EXPECT_EQ("AATAAA", a.Query());
        EXPECT_EQ("IIIIMM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("AA----", a.Target());
        EXPECT_EQ("AATAAA", a.Query());
        EXPECT_EQ("MMIIII", a.Transcript());
    }

    // intervening match
    {
        PairwiseAlignment a = PairwiseAlignment("A-T--A", "AATAAA");

        a.Justify(LRType::LEFT);
        EXPECT_EQ("-AT--A", a.Target());
        EXPECT_EQ("AATAAA", a.Query());
        EXPECT_EQ("IMMIIM", a.Transcript());

        a.Justify(LRType::RIGHT);
        EXPECT_EQ("A-TA--", a.Target());
        EXPECT_EQ("AATAAA", a.Query());
        EXPECT_EQ("MIMMII", a.Transcript());
    }
}