@Test
public void testSearch() throws Exception {

  // We create 4 events, each with a duration of 2 hours:
  // - Event no. 1 ends way before now
  // - Event no. 2 starts before the now and ends after now
  // - Event no. 3 starts when no. 2 ends
  // - Event no. 4 starts two hours after no. 3 ends
  // So we have:  [no.1][free][no.2][no.3][free][no.4]
  final long oneHourMillis = 3600_000;
  final long nowMillis = new Date().getTime();
  final String mpId = "mpId";
  final String agentId = "agent1";
  final String orgId = new DefaultOrganization().getId();
  final Date[] eventStartDates = {
      new Date(nowMillis - 4 * oneHourMillis),
      new Date(nowMillis - oneHourMillis),
      new Date(nowMillis + oneHourMillis),
      new Date(nowMillis + 5 * oneHourMillis),
  };
  final List<Integer> indeces = Arrays.asList(0, 1, 2, 3);
  Collections.shuffle(indeces); // we want to insert in random order to test if method under test sorts correctly.
  for (int i : indeces) {
    final Date start = eventStartDates[i];
    final Date end = new Date(start.getTime() + 2 * oneHourMillis);
    schedulerDatabase.storeEvent(
        mpId + i,
        orgId,
        Opt.some(agentId),
        Opt.some(start),
        Opt.some(end),
        Opt.none(),
        Opt.none(),
        Opt.none(),
        Opt.none(),
        Opt.none(),
        Opt.none(),
        Opt.none(),
        Opt.none()
    );
  }
  // All events which start from now. expected: no.3 and no.4
  final List<ExtendedEventDto> events1 = schedulerDatabase.search(
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(2, events1.size());
  Assert.assertTrue(events1.get(0).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(events1.get(1).getMediaPackageId().equals(mpId + 3));
  // All events which start to now. expected: no.1 and no.2
  final List<ExtendedEventDto> events2 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(2, events2.size());
  Assert.assertTrue(events2.get(0).getMediaPackageId().equals(mpId + 0));
  Assert.assertTrue(events2.get(1).getMediaPackageId().equals(mpId + 1));
  // All events which end from now. expected: no.2, no.3, and no.4
  final List<ExtendedEventDto> events3 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(3, events3.size());
  Assert.assertTrue(events3.get(0).getMediaPackageId().equals(mpId + 1));
  Assert.assertTrue(events3.get(1).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(events3.get(2).getMediaPackageId().equals(mpId + 3));
  // All events which end to now. expected: no.1,
  final List<ExtendedEventDto> events4 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none()
  );
  Assert.assertEquals(1, events4.size());
  Assert.assertTrue(events4.get(0).getMediaPackageId().equals(mpId + 0));
  // All events which start from now AND start to now -> illegal combination, no results expected
  Assert.assertTrue(schedulerDatabase.search(
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none(),
      Opt.none()
  ).isEmpty());
  // All events which end from now AND end to now -> illegal combination, no results expected
  Assert.assertTrue(schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.some(new Date(nowMillis)),
      Opt.none()
  ).isEmpty());
  // All events which start from now AND end to now -> illegal combination, no results expected
  Assert.assertTrue(schedulerDatabase.search(
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none()
  ).isEmpty());
  // All events which start from now + 1 hour. expected: no. 3 and no. 4
  final List<ExtendedEventDto> events5 = schedulerDatabase.search(
      Opt.none(),
      Opt.some(new Date(nowMillis + oneHourMillis)),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(2, events5.size());
  Assert.assertTrue(events5.get(0).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(events5.get(1).getMediaPackageId().equals(mpId + 3));
  // All events which start to now + 1 hour. expected: no. 1 and no. 2, but not no. 3
  final List<ExtendedEventDto> events6 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis + oneHourMillis)),
      Opt.none(),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(2, events6.size());
  Assert.assertTrue(events6.get(0).getMediaPackageId().equals(mpId + 0));
  Assert.assertTrue(events6.get(1).getMediaPackageId().equals(mpId + 1));
  // All events which end from now + 1 hour. expected: no2., no.3, and no.4
  final List<ExtendedEventDto> events7 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis + oneHourMillis)),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(3, events7.size());
  Assert.assertTrue(events7.get(0).getMediaPackageId().equals(mpId + 1));
  Assert.assertTrue(events7.get(1).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(events7.get(2).getMediaPackageId().equals(mpId + 3));
  // All events which end to now + 1 hour. expected: no.1
  final List<ExtendedEventDto> events8 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis + oneHourMillis)),
      Opt.none()
  );
  Assert.assertEquals(1, events8.size());
  Assert.assertTrue(events8.get(0).getMediaPackageId().equals(mpId + 0));
  // No start/end dates given. expected: all events are returned
  final List<ExtendedEventDto> events9 = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(4, events9.size());
  Assert.assertTrue(events9.get(0).getMediaPackageId().equals(mpId + 0));
  Assert.assertTrue(events9.get(1).getMediaPackageId().equals(mpId + 1));
  Assert.assertTrue(events9.get(2).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(events9.get(3).getMediaPackageId().equals(mpId + 3));
  // All events which start to now and end to now. expected: no. 1
  final List<ExtendedEventDto> eventsA = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none()
  );
  Assert.assertEquals(1, eventsA.size());
  Assert.assertTrue(eventsA.get(0).getMediaPackageId().equals(mpId + 0));
  // All events which start to now and end from now. expected: no. 2
  final List<ExtendedEventDto> eventsB = schedulerDatabase.search(
      Opt.none(),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(1, eventsB.size());
  Assert.assertTrue(eventsB.get(0).getMediaPackageId().equals(mpId + 1));
  // All events which start from now and end from now. expected: no. 3 and no. 4
  final List<ExtendedEventDto> eventsC = schedulerDatabase.search(
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.some(new Date(nowMillis)),
      Opt.none(),
      Opt.none()
  );
  Assert.assertEquals(2, eventsC.size());
  Assert.assertTrue(eventsC.get(0).getMediaPackageId().equals(mpId + 2));
  Assert.assertTrue(eventsC.get(1).getMediaPackageId().equals(mpId + 3));
}