@Test
  public void shouldSyncReposToDisk() throws ClassNotFoundException, IOException {
    SubsetSizeRepo subsetRepo = factory.createSubsetRepo("dev", LATEST_VERSION);
    SuiteTimeRepo suiteTimeRepo = factory.createSuiteTimeRepo("dev", LATEST_VERSION);
    SuiteResultRepo suiteResultRepo = factory.createSuiteResultRepo("dev", LATEST_VERSION);
    subsetRepo.add(new SubsetSizeEntry(10));
    suiteTimeRepo.update(new SuiteTimeEntry("foo.bar.Quux", 25));
    suiteResultRepo.update(new SuiteResultEntry("foo.bar.Baz", true));

    assertThat(
        "No files should exist as sync on this factory has never been called.",
        baseDir.list().length,
        is(0));

    factory.syncReposToDisk();

    assertThat(
        "Files should exist as sync on this factory has been called.",
        baseDir.list().length,
        is(3));

    assertContentIs(EntryRepoFactory.name("dev", LATEST_VERSION, SUBSET_SIZE), "10");
    assertContentIs(EntryRepoFactory.name("dev", LATEST_VERSION, SUITE_TIME), "foo.bar.Quux: 25");
    assertContentIs(
        EntryRepoFactory.name("dev", LATEST_VERSION, SUITE_RESULT), "foo.bar.Baz: true");
  }
 @Test
 public void shouldPurgeDiskDumpAndRepositoryWhenAsked()
     throws IOException, ClassNotFoundException, InterruptedException {
   SuiteTimeRepo fooRepo = factory.createSuiteTimeRepo("foo", LATEST_VERSION);
   fooRepo.update(new SuiteTimeEntry("foo.bar.Baz", 15));
   fooRepo.update(new SuiteTimeEntry("foo.bar.Quux", 80));
   final Thread exitHook = factory.exitHook();
   exitHook.start();
   exitHook.join();
   factory.purge(fooRepo.identifier);
   fooRepo = factory.createSuiteTimeRepo("foo", LATEST_VERSION);
   assertThat(fooRepo.list().size(), is(0));
   fooRepo = new EntryRepoFactory(env()).createSuiteTimeRepo("foo", LATEST_VERSION);
   assertThat(fooRepo.list().size(), is(0));
 }
  @Test
  public void should_NOT_SyncReposToDisk_unlessDirty() throws ClassNotFoundException, IOException {
    SubsetSizeRepo subsetRepo = factory.createSubsetRepo("dev", LATEST_VERSION);
    SuiteTimeRepo suiteTimeRepo = factory.createSuiteTimeRepo("dev", LATEST_VERSION);
    SuiteResultRepo suiteResultRepo = factory.createSuiteResultRepo("dev", LATEST_VERSION);
    subsetRepo.add(new SubsetSizeEntry(10));
    suiteTimeRepo.update(new SuiteTimeEntry("foo.bar.Quux", 25));
    suiteResultRepo.update(new SuiteResultEntry("foo.bar.Baz", true));

    factory.syncReposToDisk();

    FileUtils.cleanDirectory(baseDir);

    assertThat(baseDir.list().length, is(0));

    factory.syncReposToDisk();

    assertThat(
        "No files should exist as no repos were dirty when sync-to-disk was called.",
        baseDir.list().length,
        is(0));

    subsetRepo.add(new SubsetSizeEntry(21));
    suiteTimeRepo.update(new SuiteTimeEntry("foo.bar.Bang", 35));
    suiteResultRepo.update(new SuiteResultEntry("foo.bar.Baz", true));

    factory.syncReposToDisk();

    assertThat(
        "Files should exist as sync on this factory has been called.",
        baseDir.list().length,
        is(3));

    assertContentIs(EntryRepoFactory.name("dev", LATEST_VERSION, SUBSET_SIZE), "10", "21");
    assertContentIs(
        EntryRepoFactory.name("dev", LATEST_VERSION, SUITE_TIME),
        "foo.bar.Quux: 25",
        "foo.bar.Bang: 35");
    assertContentIs(
        EntryRepoFactory.name("dev", LATEST_VERSION, SUITE_RESULT), "foo.bar.Baz: true");
  }
  @Test
  public void shouldBeAbleToLoadFromDumpedFile()
      throws ClassNotFoundException, IOException, InterruptedException {
    SubsetSizeRepo subsetSizeRepo = factory.createSubsetRepo("foo", LATEST_VERSION);
    subsetSizeRepo.add(new SubsetSizeEntry(50));
    subsetSizeRepo.add(new SubsetSizeEntry(100));
    subsetSizeRepo.add(new SubsetSizeEntry(200));

    SuiteTimeRepo subsetTimeRepo = factory.createSuiteTimeRepo("bar", LATEST_VERSION);
    subsetTimeRepo.update(new SuiteTimeEntry("foo.bar.Baz", 10));
    subsetTimeRepo.update(new SuiteTimeEntry("bar.baz.Quux", 20));

    SuiteResultRepo subsetResultRepo = factory.createSuiteResultRepo("baz", LATEST_VERSION);
    subsetResultRepo.update(new SuiteResultEntry("foo.bar.Baz", true));
    subsetResultRepo.update(new SuiteResultEntry("bar.baz.Quux", false));

    Thread exitHook = factory.exitHook();
    exitHook.start();
    exitHook.join();
    EntryRepoFactory otherFactoryInstance = new EntryRepoFactory(env());
    assertThat(
        otherFactoryInstance.createSubsetRepo("foo", LATEST_VERSION).list(),
        is(
            (Collection<SubsetSizeEntry>)
                Arrays.asList(
                    new SubsetSizeEntry(50), new SubsetSizeEntry(100), new SubsetSizeEntry(200))));
    assertThat(
        otherFactoryInstance.createSuiteTimeRepo("bar", LATEST_VERSION).list().size(), is(2));
    assertThat(
        otherFactoryInstance.createSuiteTimeRepo("bar", LATEST_VERSION).list(),
        hasItems(new SuiteTimeEntry("foo.bar.Baz", 10), new SuiteTimeEntry("bar.baz.Quux", 20)));
    assertThat(
        otherFactoryInstance.createSuiteResultRepo("baz", LATEST_VERSION).list().size(), is(2));
    assertThat(
        otherFactoryInstance.createSuiteResultRepo("baz", LATEST_VERSION).list(),
        hasItems(
            new SuiteResultEntry("foo.bar.Baz", true),
            new SuiteResultEntry("bar.baz.Quux", false)));
  }
  @Test
  public void shouldPurgeDiskDumpAndRepositoryOlderThanGivenTime()
      throws IOException, ClassNotFoundException, InterruptedException {
    final GregorianCalendar[] cal = new GregorianCalendar[1];
    final TimeProvider timeProvider =
        new TimeProvider() {
          @Override
          public GregorianCalendar cal() {
            GregorianCalendar gregorianCalendar = cal[0];
            return gregorianCalendar == null ? null : (GregorianCalendar) gregorianCalendar.clone();
          }

          @Override
          public Date now() {
            return cal().getTime();
          }
        };
    final EntryRepoFactory factory = new EntryRepoFactory(baseDir, timeProvider);

    cal[0] = new GregorianCalendar(2010, 6, 7, 0, 37, 12);

    SuiteTimeRepo repo = factory.createSuiteTimeRepo("foo", LATEST_VERSION);
    repo.update(new SuiteTimeEntry("foo.bar.Baz", 15));
    repo.update(new SuiteTimeEntry("foo.bar.Quux", 80));

    Collection<SuiteTimeEntry> oldList = repo.list("old");
    assertThat(oldList.size(), is(2));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Baz", 15)));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Quux", 80)));

    repo.update(new SuiteTimeEntry("foo.bar.Bang", 130));
    repo.update(new SuiteTimeEntry("foo.bar.Baz", 20));

    oldList = repo.list("old");
    assertThat(oldList.size(), is(2));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Baz", 15)));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Quux", 80)));

    cal[0] = new GregorianCalendar(2010, 6, 9, 0, 37, 12);
    Collection<SuiteTimeEntry> notSoOld = repo.list("not_so_old");
    assertThat(notSoOld.size(), is(3));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Baz", 20)));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Quux", 80)));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Bang", 130)));

    repo.update(new SuiteTimeEntry("foo.bar.Foo", 12));

    final Thread exitHook = factory.exitHook();
    exitHook.start();
    exitHook.join();

    cal[0] = new GregorianCalendar(2010, 6, 10, 0, 37, 12);
    factory.purgeVersionsOlderThan(2);

    oldList = repo.list("old");
    assertThat(oldList.size(), is(4));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Baz", 20)));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Quux", 80)));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Bang", 130)));
    assertThat(oldList, hasItem(new SuiteTimeEntry("foo.bar.Foo", 12)));

    notSoOld = repo.list("not_so_old");
    assertThat(notSoOld.size(), is(3));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Baz", 20)));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Quux", 80)));
    assertThat(notSoOld, hasItem(new SuiteTimeEntry("foo.bar.Bang", 130)));
  }