Skip to content
Snippets Groups Projects
TimeSplitterTest.h 18.3 KiB
Newer Older
/*
 * TimeSplitterTest.h
 *
 *  Created on: Sep 24, 2010
 *      Author: janik
 */

#ifndef TIMESPLITTERTEST_H_
#define TIMESPLITTERTEST_H_

#include <cxxtest/TestSuite.h>
#include <ctime>
#include "MantidKernel/TimeSplitter.h"
#include "MantidKernel/DateAndTime.h"

using namespace Mantid::Kernel;

class TimeSplitterTest : public CxxTest::TestSuite {
public:
  //----------------------------------------------------------------------------
  /** Tests the AND operator checking for overlap between two
   * SplittingIntervals.
   */
  void test_SplittingInterval_AND() {
    DateAndTime start_a, stop_a, start_b, stop_b;
    start_a = DateAndTime("2007-11-30T16:17:10");
    stop_a = DateAndTime("2007-11-30T16:17:20");
    SplittingInterval a(start_a, stop_a, 0);

    SplittingInterval b, c;
    // b is all inside a
    start_b = DateAndTime("2007-11-30T16:17:12");
    stop_b = DateAndTime("2007-11-30T16:17:18");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_b);
    TS_ASSERT_EQUALS(c.stop(), stop_b);
    start_b = DateAndTime("2007-11-30T16:17:05");
    stop_b = DateAndTime("2007-11-30T16:17:23");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_a);
    TS_ASSERT_EQUALS(c.stop(), stop_a);
    start_b = DateAndTime("2007-11-30T16:17:12");
    stop_b = DateAndTime("2007-11-30T16:17:25");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_b);
    TS_ASSERT_EQUALS(c.stop(), stop_a);
    start_b = DateAndTime("2007-11-30T16:17:05");
    stop_b = DateAndTime("2007-11-30T16:17:15");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_a);
    TS_ASSERT_EQUALS(c.stop(), stop_b);
    start_b = DateAndTime("2007-11-30T16:17:01");
    stop_b = DateAndTime("2007-11-30T16:17:02");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(!a.overlaps(b));
    TS_ASSERT_LESS_THAN_EQUALS(c.duration(), 0.0);
    start_b = DateAndTime("2007-11-30T16:17:30");
    stop_b = DateAndTime("2007-11-30T16:17:42");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a & b;
    TS_ASSERT(!a.overlaps(b));
    TS_ASSERT_LESS_THAN_EQUALS(c.duration(), 0.0);
  }

  //----------------------------------------------------------------------------
  /** Tests the AND operator checking for overlap between two
   * SplittingIntervals.
   */
  void test_SplittingInterval_OR() {
    DateAndTime start_a, stop_a, start_b, stop_b;
    start_a = DateAndTime("2007-11-30T16:17:10");
    stop_a = DateAndTime("2007-11-30T16:17:20");
    SplittingInterval a(start_a, stop_a, 0);

    SplittingInterval b, c;
    // b is all inside a
    start_b = DateAndTime("2007-11-30T16:17:12");
    stop_b = DateAndTime("2007-11-30T16:17:18");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a | b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_a);
    TS_ASSERT_EQUALS(c.stop(), stop_a);
    start_b = DateAndTime("2007-11-30T16:17:05");
    stop_b = DateAndTime("2007-11-30T16:17:23");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a | b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_b);
    TS_ASSERT_EQUALS(c.stop(), stop_b);
    start_b = DateAndTime("2007-11-30T16:17:12");
    stop_b = DateAndTime("2007-11-30T16:17:25");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a | b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_a);
    TS_ASSERT_EQUALS(c.stop(), stop_b);
    start_b = DateAndTime("2007-11-30T16:17:05");
    stop_b = DateAndTime("2007-11-30T16:17:15");
    b = SplittingInterval(start_b, stop_b, 0);
    c = a | b;
    TS_ASSERT(a.overlaps(b));
    TS_ASSERT_EQUALS(c.start(), start_b);
    TS_ASSERT_EQUALS(c.stop(), stop_a);
    // No overlap (b < a) - This throws an exception because you need two
    // outputs!
    start_b = DateAndTime("2007-11-30T16:17:01");
    stop_b = DateAndTime("2007-11-30T16:17:02");
    b = SplittingInterval(start_b, stop_b, 0);
    TS_ASSERT(!a.overlaps(b));
    TS_ASSERT_THROWS(c = a | b;, std::invalid_argument);
    start_b = DateAndTime("2007-11-30T16:17:30");
    stop_b = DateAndTime("2007-11-30T16:17:42");
    b = SplittingInterval(start_b, stop_b, 0);
    TS_ASSERT(!a.overlaps(b));
    TS_ASSERT_THROWS(c = a | b;, std::invalid_argument);
  }

  //----------------------------------------------------------------------------
  void test_AND() {
    // Make a splitter
    TimeSplitterType a, b;
    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:17:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:20");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:40");
    stop = DateAndTime("2007-11-30T16:17:50");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:00");
    stop = DateAndTime("2007-11-30T16:18:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:20");
    stop = DateAndTime("2007-11-30T16:18:30");
    a.push_back(SplittingInterval(start, stop, 0));
    // Smaller than the first one
    start = DateAndTime("2007-11-30T16:17:01");
    stop = DateAndTime("2007-11-30T16:17:25");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:26");
    stop = DateAndTime("2007-11-30T16:17:27");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:45");
    stop = DateAndTime("2007-11-30T16:18:15");
    b.push_back(SplittingInterval(start, stop, 0));
    // Now AND the splitters (filters) together
    TS_ASSERT_EQUALS(c.size(), 5);
    if (c.size() < 5)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:01"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:10"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:20"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:25"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:26"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:27"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:45"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:50"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:18:00"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:10"));
  }

  //----------------------------------------------------------------------------
  void test_OR() {
    // Make a splitter
    TimeSplitterType a, b;
    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:17:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:20");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:40");
    stop = DateAndTime("2007-11-30T16:17:50");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:00");
    stop = DateAndTime("2007-11-30T16:18:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:20");
    stop = DateAndTime("2007-11-30T16:18:30");
    a.push_back(SplittingInterval(start, stop, 0));
    // Smaller than the first one
    start = DateAndTime("2007-11-30T16:17:01");
    stop = DateAndTime("2007-11-30T16:17:25");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:26");
    stop = DateAndTime("2007-11-30T16:17:27");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:45");
    stop = DateAndTime("2007-11-30T16:18:15");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:50");
    stop = DateAndTime("2007-11-30T16:18:55");
    b.push_back(SplittingInterval(start, stop, 0));
    // Now AND the splitters (filters) together
    TS_ASSERT_EQUALS(c.size(), 4);
    if (c.size() < 4)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:00"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:30"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:40"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:15"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:18:20"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:30"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:18:50"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:55"));
  //----------------------------------------------------------------------------
  void test_OR_with_a_bad_input() {
    // Make a splitter
    TimeSplitterType a, b;

    start = DateAndTime("2007-11-30T16:17:20");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));

    // A bad (reversed) interval
    start = DateAndTime("2007-11-30T16:17:32");
    stop = DateAndTime("2007-11-30T16:17:31");
    a.push_back(SplittingInterval(start, stop, 0));

    // REVERSED interval that is before the first one
    start = DateAndTime("2007-11-30T16:17:15");
    stop = DateAndTime("2007-11-30T16:17:00");
    b.push_back(SplittingInterval(start, stop, 0));

    // Another bad interval
    start = DateAndTime("2007-11-30T16:17:45");
    stop = DateAndTime("2007-11-30T16:17:35");
    b.push_back(SplittingInterval(start, stop, 0));
    // Now AND the splitters (filters) together
    TS_ASSERT_EQUALS(c.size(), 1);
    if (c.size() < 1)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:20"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:30"));
  //----------------------------------------------------------------------------
  void test_NOT_Normal() {
    TimeSplitterType a, b, c;
    SplittingInterval i;

    //---- Normal Case ------
    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:17:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:20");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));
    // Perform the NOT operation
    TS_ASSERT_EQUALS(c.size(), 3);
    if (c.size() < 3)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime::minimum());
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:00"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:10"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:20"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:30"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime::maximum());
  }

  //----------------------------------------------------------------------------
  void test_NOT_empty() {
    TimeSplitterType a, b, c;
    SplittingInterval i;

    //---- Empty case ----------
    c = ~b;
    TS_ASSERT_EQUALS(c.size(), 1);
    if (c.size() < 1)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime::minimum());
    TS_ASSERT_EQUALS(i.stop(), DateAndTime::maximum());
  }

  //----------------------------------------------------------------------------
  void test_NOT_overlap() {
    TimeSplitterType a, b, c;
    // Overlapping case ------
    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:17:15");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:10");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));
    TS_ASSERT_EQUALS(c.size(), 2);
    if (c.size() < 3)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime::minimum());
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:00"));
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:30"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime::maximum());
  }

  //----------------------------------------------------------------------------
  void test_PLUS() {
    TimeSplitterType a, b, c;
    start = DateAndTime("2007-11-30T16:15:00");
    stop = DateAndTime("2007-11-30T16:16:00");
    b.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:18:00");
    b.push_back(SplittingInterval(start, stop, 1));
    start = DateAndTime("2007-11-30T16:18:00");
    stop = DateAndTime("2007-11-30T16:19:00");
    b.push_back(SplittingInterval(start, stop, 2));
    start = DateAndTime("2007-11-30T16:19:00");
    stop = DateAndTime("2007-11-30T16:20:00");
    b.push_back(SplittingInterval(start, stop, 3));
    start = DateAndTime("2007-11-30T16:16:50");
    stop = DateAndTime("2007-11-30T16:17:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:20");
    stop = DateAndTime("2007-11-30T16:17:30");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:17:40");
    stop = DateAndTime("2007-11-30T16:18:10");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:18:50");
    stop = DateAndTime("2007-11-30T16:18:55");
    a.push_back(SplittingInterval(start, stop, 0));
    start = DateAndTime("2007-11-30T16:22:20");
    stop = DateAndTime("2007-11-30T16:22:30");
    a.push_back(SplittingInterval(start, stop, 0));
    // Do the PLUS operation
    TS_ASSERT_EQUALS(c.size(), 5);
    if (c.size() < 5)
      return; // avoid segfaults if this part of the test fails
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:00"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:10"));
    TS_ASSERT_EQUALS(i.index(), 1);
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:20"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:17:30"));
    TS_ASSERT_EQUALS(i.index(), 1);
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:17:40"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:00"));
    TS_ASSERT_EQUALS(i.index(), 1);
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:18:00"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:10"));
    TS_ASSERT_EQUALS(i.index(), 2);
    TS_ASSERT_EQUALS(i.start(), DateAndTime("2007-11-30T16:18:50"));
    TS_ASSERT_EQUALS(i.stop(), DateAndTime("2007-11-30T16:18:55"));
    TS_ASSERT_EQUALS(i.index(), 2);
    // This fails since you can't add splitters together
    TS_ASSERT_THROWS(b + b, std::invalid_argument);
  //----------------------------------------------------------------------------
  void test_sort() {
    DateAndTime start, stop;
    TimeSplitterType b;

    //  the splitter ------
    start = DateAndTime("2007-11-30T16:15:00");
    stop = DateAndTime("2007-11-30T16:16:00");
    b.push_back(SplittingInterval(start, stop, 0));

    start = DateAndTime("2007-11-30T16:19:00");
    stop = DateAndTime("2007-11-30T16:20:00");
    b.push_back(SplittingInterval(start, stop, 3));

    start = DateAndTime("2007-11-30T16:18:00");
    stop = DateAndTime("2007-11-30T16:19:00");
    b.push_back(SplittingInterval(start, stop, 2));

    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:18:00");
    b.push_back(SplittingInterval(start, stop, 1));

    std::sort(b.begin(), b.end());

    TS_ASSERT_EQUALS(b[0].start(), DateAndTime("2007-11-30T16:15:00"));
    TS_ASSERT_EQUALS(b[1].start(), DateAndTime("2007-11-30T16:17:00"));
    TS_ASSERT_EQUALS(b[2].start(), DateAndTime("2007-11-30T16:18:00"));
    TS_ASSERT_EQUALS(b[3].start(), DateAndTime("2007-11-30T16:19:00"));
  }

  //----------------------------------------------------------------------------
  void test_find() {
    DateAndTime start, stop;
    TimeSplitterType b;

    //  the splitter ------
    start = DateAndTime("2007-11-30T16:15:00");
    stop = DateAndTime("2007-11-30T16:16:00");
    b.push_back(SplittingInterval(start, stop, 0));

    start = DateAndTime("2007-11-30T16:19:00");
    stop = DateAndTime("2007-11-30T16:20:00");
    b.push_back(SplittingInterval(start, stop, 3));

    start = DateAndTime("2007-11-30T16:18:00");
    stop = DateAndTime("2007-11-30T16:19:00");
    b.push_back(SplittingInterval(start, stop, 2));

    start = DateAndTime("2007-11-30T16:17:00");
    stop = DateAndTime("2007-11-30T16:18:00");
    b.push_back(SplittingInterval(start, stop, 1));

    std::sort(b.begin(), b.end());

    TimeSplitterType::iterator sit;

    SplittingInterval temp1(DateAndTime("2007-11-30T16:17:00"),
                            DateAndTime("2007-11-30T16:17:00"), -1);
    sit = std::lower_bound(b.begin(), b.end(), temp1);
    int index1 = int(sit - b.begin());
    TS_ASSERT_EQUALS(index1, 1);

    SplittingInterval temp2(DateAndTime("2007-11-30T16:17:10"),
                            DateAndTime("2007-11-30T16:17:00"), -1);
    sit = std::lower_bound(b.begin(), b.end(), temp2);
    int index2 = int(sit - b.begin());
    TS_ASSERT_EQUALS(index2, 2);
  }