package com.github.triceo.splitlog;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import com.github.triceo.splitlog.api.Follower;
import com.github.triceo.splitlog.api.LogWatch;
import com.github.triceo.splitlog.api.LogWatchBuilder;
import com.github.triceo.splitlog.api.MergingFollower;
import com.github.triceo.splitlog.formatters.NoopMessageFormatter;
public class MergingTest extends DefaultFollowerBaseTest {
private static final String MESSAGE_1 = "Message";
private static final String MESSAGE_2 = "Second Message";
private static final String MESSAGE_3 = "Third Message";
private static final String MESSAGE_4 = "Fourth Message";
private static final String MESSAGE_5 = "Fifth Message";
@Test
public void testMergeWithDifferentWatches() {
// write into first file
final LogWatch watch1 = LogWatchBuilder.getDefault().watchedFile(LogWriter.createTempFile())
.build();
final Follower follower1 = watch1.startFollowing();
LogWriter.write(follower1, MergingTest.MESSAGE_1);
// write into second file
final LogWatch watch2 = LogWatchBuilder.getDefault().watchedFile(LogWriter.createTempFile())
.build();
final Follower follower2 = watch2.startFollowing();
LogWriter.write(follower2, MergingTest.MESSAGE_2);
// merge both
final MergingFollower merge = follower2.mergeWith(follower1);
Assertions.assertThat(merge.getMerged()).containsOnly(follower1, follower2);
Assertions.assertThat(merge.getMessages()).hasSize(0); // zero ACCEPTED
LogWriter.write(follower2, MergingTest.MESSAGE_3);
Assertions.assertThat(merge.getMessages()).hasSize(1); // one ACCEPTED
LogWriter.write(follower1, MergingTest.MESSAGE_4);
// third follows the first file; merge should have the message just once
final Follower follower3 = watch1.startFollowing();
final MergingFollower merge2 = follower3.mergeWith(merge);
Assertions.assertThat(merge.getMerged()).containsOnly(follower1, follower2);
Assertions.assertThat(merge2).isNotSameAs(merge);
Assertions.assertThat(merge2.getMerged()).containsOnly(follower1, follower2, follower3);
LogWriter.write(follower3, MergingTest.MESSAGE_5);
Assertions.assertThat(merge.getMessages()).hasSize(3);
Assertions.assertThat(merge2.getMessages()).hasSize(3);
// test writing
final Collection<String> messages = new LinkedList<>();
messages.add(MergingTest.MESSAGE_1);
messages.add(MergingTest.MESSAGE_2);
messages.add(MergingTest.MESSAGE_4);
try {
final File f = LogWriter.createTempFile();
merge2.write(new FileOutputStream(f), NoopMessageFormatter.INSTANCE);
Assertions.assertThat(f).exists();
final List<String> lines = FileUtils.readLines(f, "UTF-8");
Assertions.assertThat(lines).isEqualTo(messages);
} catch (final Exception e) {
Assertions.fail("Couldn't write to file.");
}
// and now separate the second, making MESSAGE_2 disappear
final MergingFollower merge3 = merge2.remove(follower2);
Assertions.assertThat(merge2.getMerged()).contains(follower2);
Assertions.assertThat(merge3.getMerged()).doesNotContain(follower2);
Assertions.assertThat(merge3.getMessages()).hasSize(2);
// now only MESSAGE_4 remains ACCEPTED
final MergingFollower merge4 = merge3.remove(follower1);
Assertions.assertThat(merge2.getMerged()).contains(follower1);
Assertions.assertThat(merge4.getMerged()).doesNotContain(follower1);
Assertions.assertThat(merge4.getMessages()).hasSize(1);
// and now stop the followers to see what happens to the merges
follower3.stop();
Assertions.assertThat(follower3.isStopped()).isTrue();
Assertions.assertThat(merge4.isStopped()).isTrue();
Assertions.assertThat(merge3.isStopped()).isFalse();
Assertions.assertThat(merge2.isStopped()).isFalse();
Assertions.assertThat(merge.isStopped()).isFalse();
// first watch is terminated, second one remains alive
watch1.stop();
Assertions.assertThat(follower1.isStopped()).isTrue();
Assertions.assertThat(merge4.isStopped()).isTrue();
Assertions.assertThat(merge3.isStopped()).isTrue();
Assertions.assertThat(merge2.isStopped()).isFalse();
Assertions.assertThat(follower2.isStopped()).isFalse();
Assertions.assertThat(merge.isStopped()).isFalse();
merge.stop();
Assertions.assertThat(merge.isStopped()).isTrue();
Assertions.assertThat(merge2.isStopped()).isTrue();
Assertions.assertThat(follower2.isStopped()).isTrue();
}
@Test
public void testMergeWithSameLogWatch() {
final Follower f = this.getLogWatch().startFollowing();
final Follower f2 = this.getLogWatch().startFollowing();
final MergingFollower mf = f.mergeWith(f2);
// send the message; the merged should still contain only the one
LogWriter.write(f, "test");
LogWriter.write(f2, "test2");
Assertions.assertThat(mf.getMessages()).hasSize(1);
// add third follower, will only receive the second message
final Follower f3 = this.getLogWatch().startFollowing();
LogWriter.write(f3, "test3");
final MergingFollower mf2 = mf.mergeWith(f3);
Assertions.assertThat(mf2).isNotEqualTo(mf);
Assertions.assertThat(mf.getMessages()).hasSize(2);
Assertions.assertThat(mf2.getMessages()).hasSize(2);
// remove both followers from first merge, verify results
final MergingFollower mf3 = mf.remove(f);
Assertions.assertThat(mf3.getMessages()).hasSize(2);
Assertions.assertThat(mf3.isStopped()).isFalse();
Assertions.assertThat(this.getLogWatch().stopFollowing(f2)).isTrue();
Assertions.assertThat(mf3.isStopped()).isTrue(); // no followers are
// following
Assertions.assertThat(mf.getMessages()).hasSize(2);
Assertions.assertThat(mf3.remove(f2)).isEqualTo(null);
// none of these changes should have affected the second merge
Assertions.assertThat(mf2.getMessages()).hasSize(2);
final MergingFollower mf5 = mf2.remove(f2);
this.getLogWatch().stopFollowing(f);
Assertions.assertThat(mf5.getMessages()).hasSize(2);
final MergingFollower mf6 = mf5.remove(f);
Assertions.assertThat(mf6.getMessages()).hasSize(1);
this.getLogWatch().stop();
Assertions.assertThat(mf.isStopped()).isTrue();
}
@Test(expected = IllegalArgumentException.class)
public void testMergeWithSelf() {
final Follower f = this.getLogWatch().startFollowing();
f.mergeWith(f);
}
@Test(expected = IllegalArgumentException.class)
public void testMergeWithSelf2() {
final Follower f = this.getLogWatch().startFollowing();
final Follower f2 = this.getLogWatch().startFollowing();
final MergingFollower mf = f.mergeWith(f2);
mf.mergeWith(mf);
}
}