// ./tests/catch2-tests [section] -s


/////////////////////// Qt includes
#include <QDebug>
#include <QString>
#include <QDir>


/////////////////////// Catch2 includes
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_floating_point.hpp>


/////////////////////// Local includes
#include "TestUtils.hpp"
#include "MsXpS/libXpertMassCore/SequenceRanges.hpp"


namespace MsXpS
{
namespace libXpertMassCore
{


SCENARIO("Construction of a SequenceRanges instance", "[SequenceRanges]")
{
  QString sequence_range_string_1("[50-150]");
  SequenceRange sequence_range_1(50, 150);

  QString sequence_range_string_2("[40-160]");
  SequenceRange sequence_range_2(40, 160);

  QString sequence_range_string_3("[30-170]");
  SequenceRange sequence_range_3(30, 170);

  QString all_three_sequence_range_strings = QString("%1%2%3")
                                               .arg(sequence_range_string_1)
                                               .arg(sequence_range_string_2)
                                               .arg(sequence_range_string_3);

  GIVEN("Construction with no argument")
  {
    SequenceRanges sequence_ranges;

    WHEN("A comment is set to it")
    {
      sequence_ranges.setComment("Comment");

      THEN("The comment should be set")
      {
        REQUIRE(sequence_ranges.getComment().toStdString() == "Comment");
      }
    }
  }

  GIVEN(
    "Construction of a SequenceRanges instance with a string representing "
    "three SequenceRange instances")
  {
    SequenceRanges sequence_ranges(all_three_sequence_range_strings);

    THEN("The list must have size 3")
    {
      REQUIRE(sequence_ranges.size() == 3);

      AND_THEN("All the members of the list should have proper values")
      {
        SequenceRange first_sequence_range =
          sequence_ranges.getRangeCstRefAt(0);

        REQUIRE(first_sequence_range.start == sequence_range_1.start - 1);
        REQUIRE(first_sequence_range.stop == sequence_range_1.stop - 1);

        SequenceRange second_sequence_range =
          sequence_ranges.getRangeCstRefAt(1);

        REQUIRE(second_sequence_range.start == sequence_range_2.start - 1);
        REQUIRE(second_sequence_range.stop == sequence_range_2.stop - 1);

        SequenceRange third_sequence_range =
          sequence_ranges.getRangeCstRefAt(2);

        REQUIRE(third_sequence_range.start == sequence_range_3.start - 1);
        REQUIRE(third_sequence_range.stop == sequence_range_3.stop - 1);
      }
    }
  }

  GIVEN(
    "An incorrect string incorrectly representing three SequenceRange (missing "
    "1 "
    "'[')")
  {
    QString all_three_sequence_range_strings("50-150][40-160][30-170]");

    WHEN("Constructing a SequenceRanges instance")
    {
      SequenceRanges sequence_ranges(all_three_sequence_range_strings);

      THEN("The list is created empty")
      {
        REQUIRE(sequence_ranges.size() == 0);
      }
    }
  }

  GIVEN(
    "An incorrect string incorrectly representing three SequenceRange (missing "
    "1 "
    "']'")
  {
    QString all_three_sequence_range_strings("[50-150][40-160[30-170]");

    WHEN("Constructing a SequenceRanges instance")
    {
      SequenceRanges sequence_ranges(all_three_sequence_range_strings);

      THEN("The list is created empty")
      {
        REQUIRE(sequence_ranges.size() == 0);
      }
    }
  }

  GIVEN(
    "An incorrect string incorrectly representing three SequenceRange (missing "
    "1 "
    "']' and 1 '['")
  {
    QString all_three_sequence_range_strings("50-150][40-160[30-170]");

    WHEN("Constructing a SequenceRanges instance")
    {
      SequenceRanges sequence_ranges(all_three_sequence_range_strings);

      THEN("The list is created empty")
      {
        REQUIRE(sequence_ranges.size() == 0);
      }
    }
  }

  GIVEN(
    "An incorrect string incorrectly representing three SequenceRange (missing "
    "1 "
    "'-'")
  {
    QString all_three_sequence_range_strings("[50-150][40-160][30 170]");

    WHEN("Constructing a SequenceRanges instance")
    {
      SequenceRanges sequence_ranges(all_three_sequence_range_strings);

      THEN("The list is created empty")
      {
        REQUIRE(sequence_ranges.size() == 0);
      }
    }
  }

  GIVEN("Construction with a comment and no list; and SequenceRange objects")
  {
    SequenceRanges sequence_ranges;
    sequence_ranges.setComment("Comment");
    REQUIRE(sequence_ranges.getComment().toStdString() == "Comment");
    REQUIRE(sequence_ranges.size() == 0);

    WHEN("One SequenceRange object is appended to the list")
    {
      sequence_ranges.appendSequenceRange(sequence_range_1);

      THEN(
        "The list must have size 1, and that object has to be the one appended")
      {
        REQUIRE(sequence_ranges.size() == 1);
        REQUIRE(sequence_ranges.getRangeCstRefAt(0) == sequence_range_1);
      }

      AND_WHEN("Another SequenceRange object is appended to the list")
      {
        sequence_ranges.appendSequenceRange(sequence_range_2);

        THEN(
          "The list must have size 2, and that object has to be the last of "
          "the list")
        {
          REQUIRE(sequence_ranges.size() == 2);
          REQUIRE(sequence_ranges.getRangeCstRefAt(sequence_ranges.size() -
                                                   1) == sequence_range_2);
        }

        AND_WHEN(
          "That 2-sized SequenceRanges instance is copied (copy-constructor "
          "with reference)")
        {
          SequenceRanges new_sequence_ranges(sequence_ranges);

          THEN("The two SequenceRanges instances must have the same data")
          {
            REQUIRE(new_sequence_ranges.getComment().toStdString() ==
                    sequence_ranges.getComment().toStdString());
            REQUIRE(new_sequence_ranges.size() == sequence_ranges.size());
            REQUIRE(new_sequence_ranges.getRangeCstRefAt(0) ==
                    sequence_ranges.getRangeCstRefAt(0));
            REQUIRE(
              new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() -
                                                   1) ==
              sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() - 1));
          }
        }

        AND_WHEN(
          "That 2-sized SequenceRanges instance is copied (assignment "
          "operator) to itself,  a reference to itself is returned")
        {
          REQUIRE((sequence_ranges = sequence_ranges) == sequence_ranges);
        }

        AND_WHEN(
          "That 2-sized SequenceRanges instance is copied (assignment "
          "operator)")
        {
          SequenceRanges new_sequence_ranges;
          new_sequence_ranges = sequence_ranges;

          THEN("The two SequenceRanges instances must have the same data")
          {
            REQUIRE(new_sequence_ranges.getComment().toStdString() ==
                    sequence_ranges.getComment().toStdString());
            REQUIRE(new_sequence_ranges.size() == sequence_ranges.size());
            REQUIRE(new_sequence_ranges.getRangeCstRefAt(0) ==
                    sequence_ranges.getRangeCstRefAt(0));
            REQUIRE(
              new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() -
                                                   1) ==
              sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1));
          }
        }
      }
    }
  }
}

SCENARIO(
  "Empty SequenceRanges instances can be filled-in after construction with "
  "other SequenceRanges",
  "[SequenceRanges]")
{

  GIVEN(
    "Construction of a SequenceRanges instance with two SequenceRange "
    "instances")
  {
    SequenceRange sequence_range_1(50, 150);
    SequenceRange sequence_range_2(40, 160);
    SequenceRange sequence_range_3(30, 170);

    SequenceRanges sequence_ranges_0;
    sequence_ranges_0.setComment("Giver");
    sequence_ranges_0.appendSequenceRange(sequence_range_1);
    sequence_ranges_0.appendSequenceRange(sequence_range_2);

    REQUIRE(sequence_ranges_0.size() == 2);
    REQUIRE(sequence_ranges_0.getRangeCstRefAt(0) == sequence_range_1);
    REQUIRE(sequence_ranges_0.getRangeCstRefAt(sequence_ranges_0.size() - 1) ==
            sequence_range_2);

    AND_GIVEN("Construction of an empty SequenceRanges instance")
    {
      SequenceRanges sequence_ranges;
      sequence_ranges.setComment("Receiver");
      REQUIRE(sequence_ranges.getComment().toStdString() == "Receiver");
      REQUIRE(sequence_ranges.size() == 0);

      WHEN(
        "The first SequenceRanges instance with two items is appended to the "
        "the empty one")
      {
        sequence_ranges.appendSequenceRanges(sequence_ranges_0);

        THEN("Its size must become the same at the one that was appended")
        {
          REQUIRE(sequence_ranges.size() == sequence_ranges_0.size());
          REQUIRE(sequence_ranges.getRangeCstRefAt(0) ==
                  sequence_ranges_0.getRangeCstRefAt(0));
          REQUIRE(
            sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1) ==
            sequence_ranges_0.getRangeCstRefAt(sequence_ranges_0.size() - 1));
        }

        AND_WHEN("A new SequenceRange instance is set (not appended)")
        {
          sequence_ranges.setSequenceRange(sequence_range_3);

          THEN("The single instance has to be this last")
          {
            REQUIRE(sequence_ranges.size() == 1);
            REQUIRE(sequence_ranges.getRangeCstRefAt(0) == sequence_range_3);
          }

          AND_WHEN("A SequenceRanges instance is set (not appended)")
          {
            sequence_ranges.setSequenceRanges(sequence_ranges_0);

            THEN(
              "The previous single instance has to be lost and be replaced by "
              "the new ones")
            {
              REQUIRE(sequence_ranges.size() == 2);
              REQUIRE(sequence_ranges.getRangeCstRefAt(0) ==
                      sequence_ranges_0.getRangeCstRefAt(0));
              REQUIRE(
                sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1) ==
                sequence_ranges_0.getRangeCstRefAt(sequence_ranges_0.size() -
                                                   1));
            }
          }
        }
      }
    }
  }
}

SCENARIO(
  "Empty SequenceRanges instances can be filled in after construction with "
  "strings representative of SequenceRange instances (single or multiple)",
  "[SequenceRanges]")
{
  QString sequence_range_string_1("[50-150]");
  SequenceRange sequence_range_1(50, 150);

  QString sequence_range_string_2("[40-160]");
  SequenceRange sequence_range_2(40, 160);

  QString sequence_range_string_3("[30-170]");
  SequenceRange sequence_range_3(30, 170);

  QString all_three_sequence_range_strings = QString("%1%2%3")
                                               .arg(sequence_range_string_1)
                                               .arg(sequence_range_string_2)
                                               .arg(sequence_range_string_3);

  GIVEN("Construction with a comment and no list; and SequenceRange objects")
  {
    SequenceRanges sequence_ranges;
    sequence_ranges.setComment("Comment");
    REQUIRE(sequence_ranges.getComment().toStdString() == "Comment");
    REQUIRE(sequence_ranges.size() == 0);

    WHEN(
      "That SequenceRanges is set with one string representative of a single "
      "SequenceRange instance")
    {
      sequence_ranges.setSequenceRanges(sequence_range_string_1);

      THEN(
        "The list must have size 1, and that object has to be the one set,  "
        "with each first/second value decremented by one to convert positions "
        "to "
        "indices")
      {
        REQUIRE(sequence_ranges.size() == 1);
        REQUIRE(sequence_ranges.getRangeCstRefAt(0).start ==
                sequence_range_1.start - 1);
        REQUIRE(sequence_ranges.getRangeCstRefAt(0).stop ==
                sequence_range_1.stop - 1);
      }
    }

    WHEN(
      "That SequenceRanges is set with one string representative of three "
      "SequenceRange instances")
    {
      sequence_ranges.setSequenceRanges(all_three_sequence_range_strings);

      THEN("The list must have size 3")
      {
        REQUIRE(sequence_ranges.size() == 3);
      }

      AND_THEN("All the members of the list should have proper values")
      {
        REQUIRE(sequence_ranges.getRangeCstRefAt(0).start ==
                sequence_range_1.start - 1);
        REQUIRE(sequence_ranges.getRangeCstRefAt(0).stop ==
                sequence_range_1.stop - 1);

        REQUIRE(sequence_ranges.getRangeCstRefAt(1).start ==
                sequence_range_2.start - 1);
        REQUIRE(sequence_ranges.getRangeCstRefAt(1).stop ==
                sequence_range_2.stop - 1);

        REQUIRE(
          sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1).start ==
          sequence_range_3.start - 1);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1).stop ==
          sequence_range_3.stop - 1);
      }
    }
  }
}

SCENARIO("SequenceRanges instances can provide topological data",
         "[SequenceRanges]")
{
  GIVEN("A SequenceRanges instance with a single SequenceRange instance")
  {
    SequenceRanges sequence_ranges;

    QString all_sequence_range_strings("[1-20]");

    sequence_ranges.setSequenceRanges(all_sequence_range_strings);

    REQUIRE(sequence_ranges.size() == 1);

    std::vector<std::size_t> left_most_indices;
    std::vector<std::size_t> right_most_indices;

    WHEN("Asking for the leftmost and the rightmost SequenceRange instances")
    {
      REQUIRE(sequence_ranges.leftMostSequenceRanges(left_most_indices) == 1);
      REQUIRE(sequence_ranges.rightMostSequenceRanges(right_most_indices) == 1);

      THEN(
        "The indices should actually match the correct SequenceRange instance")
      {
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(left_most_indices.at(0)).start == 0);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(right_most_indices.at(0)).stop ==
          19);
      }
    }

    WHEN(
      "Checking if there are overlaps,  there cannot be because only one "
      "instance")
    {
      REQUIRE_FALSE(sequence_ranges.overlap());
    }

    WHEN("Checking for indices that are encompassed or not")
    {
      THEN("The results should be consistent")
      {
        REQUIRE(sequence_ranges.encompassIndex(0));
        REQUIRE(sequence_ranges.encompassIndex(19));
        REQUIRE(sequence_ranges.encompassIndex(10));
        REQUIRE_FALSE(sequence_ranges.encompassIndex(20));
      }
    }

    WHEN("Checking for indices left most SequenceRange")
    {
      THEN("The results should be consistent")
      {
        REQUIRE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));
        REQUIRE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));
      }
    }
  }

  GIVEN(
    "A SequenceRanges instance with a number of non-overlapping SequenceRange")
  {
    SequenceRanges sequence_ranges;

    QString all_sequence_range_strings("[1-20][25-45][55-100]");

    sequence_ranges.setSequenceRanges(all_sequence_range_strings);

    REQUIRE(sequence_ranges.size() == 3);

    std::vector<std::size_t> left_most_indices;
    std::vector<std::size_t> right_most_indices;

    WHEN("Asking for the leftmost and the rightmost SequenceRanges")
    {
      REQUIRE(sequence_ranges.leftMostSequenceRanges(left_most_indices) == 1);
      REQUIRE(sequence_ranges.rightMostSequenceRanges(right_most_indices) == 1);

      THEN(
        "The indices should actually match the right SequenceRange instances")
      {
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(left_most_indices.at(0)).start == 0);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(right_most_indices.at(0)).stop ==
          99);
      }
    }

    WHEN("Checking if there are overlaps, there should not be")
    {
      REQUIRE_FALSE(sequence_ranges.overlap());
    }

    WHEN("Checking for indices that are encompassed or not")
    {
      THEN("The results should be consistent")
      {
        REQUIRE(sequence_ranges.encompassIndex(0));
        REQUIRE_FALSE(sequence_ranges.encompassIndex(50));
        REQUIRE(sequence_ranges.encompassIndex(50, /*globally*/ true));
        REQUIRE(sequence_ranges.encompassIndex(99));
        REQUIRE_FALSE(sequence_ranges.encompassIndex(100));
      }
    }

    WHEN("Checking for indices left most SequenceRange")
    {
      THEN("The results should be consistent")
      {
        // "[1-20][25-45][55-100]"

        REQUIRE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(1)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(1)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(2)));
        REQUIRE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(2)));
      }
    }
  }

  GIVEN(
    "A SequenceRanges instance with a number of SequenceRange with overlaps")
  {
    SequenceRanges sequence_ranges;

    QString all_sequence_range_strings(
      "[1-20][1-30][10-50][15-80][25-100][30-100]");

    sequence_ranges.setSequenceRanges(all_sequence_range_strings);

    REQUIRE(sequence_ranges.size() == 6);

    std::vector<std::size_t> left_most_indices;
    std::vector<std::size_t> right_most_indices;

    WHEN("Asking for the leftmost and the rightmost SequenceRanges")
    {
      REQUIRE(sequence_ranges.leftMostSequenceRanges(left_most_indices) == 2);
      REQUIRE(sequence_ranges.rightMostSequenceRanges(right_most_indices) == 2);

      THEN(
        "The indices should actually match the right SequenceRange instances")
      {
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(left_most_indices.at(0)).start == 0);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(left_most_indices.back()).start ==
          0);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(right_most_indices.at(0)).stop ==
          99);
        REQUIRE(
          sequence_ranges.getRangeCstRefAt(right_most_indices.back()).stop ==
          99);
      }
    }

    WHEN("Checking if there are overlaps, there should  be")
    {
      REQUIRE(sequence_ranges.overlap());
    }

    WHEN("Checking for indices that are encompassed or not")
    {
      THEN("The results should be consistent")
      {
        REQUIRE(sequence_ranges.encompassIndex(0));
        REQUIRE(sequence_ranges.encompassIndex(49));
        REQUIRE(sequence_ranges.encompassIndex(50));
        REQUIRE(sequence_ranges.encompassIndex(99));
        REQUIRE_FALSE(sequence_ranges.encompassIndex(100));
      }
    }

    WHEN("Checking for indices left most SequenceRange")
    {
      THEN("The results should be consistent")
      {
        // "[1-20][1-30][10-50][15-80][25-100][30-100]"

        REQUIRE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(0)));

        REQUIRE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(1)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(1)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(2)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(2)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(3)));
        REQUIRE_FALSE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(3)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(4)));
        REQUIRE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(4)));

        REQUIRE_FALSE(sequence_ranges.isLeftMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(5)));
        REQUIRE(sequence_ranges.isRightMostSequenceRange(
          sequence_ranges.getRangeCstRefAt(5)));
      }
    }
  }
}

SCENARIO("SequenceRanges instances can self-describe with text strings",
         "[SequenceRanges]")
{
  QString all_three_sequence_range_strings("[50-150][40-160][30-170]");

  GIVEN("Construction with a string describing three SequenceRange instances")
  {
    SequenceRanges sequence_ranges(all_three_sequence_range_strings);

    WHEN("When asked to self-describe as indices")
    {
      QString text = sequence_ranges.indicesAsText();

      THEN("The string should be list indices and not positions")
      {
        REQUIRE(text.toStdString() == "[49-149][39-159][29-169]");
      }
    }

    WHEN("When asked to self-describe as positions")
    {
      QString text = sequence_ranges.positionsAsText();

      THEN("The string should be list positions and not indices")
      {
        REQUIRE(text.toStdString() ==
                all_three_sequence_range_strings.toStdString());
      }
    }
  }
}

SCENARIO("SequenceRanges and SequenceRange instances can be compared",
         "[SequenceRanges]")
{
  QString sequence_range_string_1("[50-150]");
  SequenceRange sequence_range_1(50, 150);

  QString sequence_range_string_2("[40-160]");
  SequenceRange sequence_range_2(40, 160);

  QString sequence_range_string_3("[30-170]");
  SequenceRange sequence_range_3(30, 170);

  QString all_three_sequence_range_strings = QString("%1%2%3")
                                               .arg(sequence_range_string_1)
                                               .arg(sequence_range_string_2)
                                               .arg(sequence_range_string_3);

  GIVEN("A SequenceRanges instance with 3 SequenceRange instances")
  {
    SequenceRanges sequence_ranges(all_three_sequence_range_strings);

    THEN("The list must have size 3")
    {
      REQUIRE(sequence_ranges.size() == 3);
    }

    AND_THEN("All the members of the list should have proper values")
    {
      REQUIRE(sequence_ranges.getRangeCstRefAt(0).start ==
              sequence_range_1.start - 1);
      REQUIRE(sequence_ranges.getRangeCstRefAt(0).stop ==
              sequence_range_1.stop - 1);

      REQUIRE(sequence_ranges.getRangeCstRefAt(1).start ==
              sequence_range_2.start - 1);
      REQUIRE(sequence_ranges.getRangeCstRefAt(1).stop ==
              sequence_range_2.stop - 1);

      REQUIRE(
        sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1).start ==
        sequence_range_3.start - 1);
      REQUIRE(
        sequence_ranges.getRangeCstRefAt(sequence_ranges.size() - 1).stop ==
        sequence_range_3.stop - 1);
    }

    WHEN("A new SequenceRanges instance is created as a copy of the first one")
    {
      SequenceRanges new_sequence_ranges(sequence_ranges);

      THEN("The new instance should be identical to the initial one")
      {
        REQUIRE(new_sequence_ranges.size() == 3);
        REQUIRE(new_sequence_ranges.getRangeCstRefAt(0).start ==
                sequence_range_1.start - 1);
        REQUIRE(new_sequence_ranges.getRangeCstRefAt(0).stop ==
                sequence_range_1.stop - 1);

        REQUIRE(new_sequence_ranges.getRangeCstRefAt(1).start ==
                sequence_range_2.start - 1);
        REQUIRE(new_sequence_ranges.getRangeCstRefAt(1).stop ==
                sequence_range_2.stop - 1);

        REQUIRE(
          new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() - 1)
            .start == sequence_range_3.start - 1);
        REQUIRE(
          new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() - 1)
            .stop == sequence_range_3.stop - 1);
      }

      AND_THEN("The comparison operators should return identity")
      {
        REQUIRE(new_sequence_ranges == sequence_ranges);
        REQUIRE_FALSE(new_sequence_ranges != sequence_ranges);
      }

      AND_WHEN("A one SequenceRange instance is modified")
      {
        // SequenceRange sequence_range_1(50, 150);
        // SequenceRange sequence_range_2(40, 160);
        // SequenceRange sequence_range_3(30, 170);

        SequenceRanges new_sequence_ranges(sequence_ranges);

        SequenceRange &sequence_range = new_sequence_ranges.getRangeRefAt(1);
        sequence_range.start          = 50;
        sequence_range.stop           = 150;

        THEN("The new instance should not be identical anymore")
        {
          REQUIRE(new_sequence_ranges.size() == 3);
          REQUIRE(new_sequence_ranges.getRangeCstRefAt(0).start ==
                  sequence_range_1.start - 1);
          REQUIRE(new_sequence_ranges.getRangeCstRefAt(0).stop ==
                  sequence_range_1.stop - 1);

          REQUIRE(new_sequence_ranges.getRangeCstRefAt(1).start == 50);
          REQUIRE(new_sequence_ranges.getRangeCstRefAt(1).stop == 150);

          REQUIRE(
            new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() - 1)
              .start == sequence_range_3.start - 1);
          REQUIRE(
            new_sequence_ranges.getRangeCstRefAt(new_sequence_ranges.size() - 1)
              .stop == sequence_range_3.stop - 1);
        }

        AND_THEN("The comparison operators should return identity")
        {
          REQUIRE(new_sequence_ranges != sequence_ranges);
          REQUIRE_FALSE(new_sequence_ranges == sequence_ranges);
        }
      }
    }
  }
}


} // namespace libXpertMassCore
} // namespace MsXpS
