/*
* This file is part of Fim - File Integrity Manager
*
* Copyright (C) 2017 Etienne Vrignaud
*
* Fim is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fim is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Fim. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fim.internal;
import org.fim.model.CompareResult;
import org.fim.model.HashMode;
import org.fim.tooling.BuildableContext;
import org.fim.tooling.BuildableState;
import org.fim.tooling.FileNameDiff;
import org.fim.tooling.StateAssert;
import org.fim.util.Logger;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
import static org.assertj.core.api.Assertions.assertThat;
import static org.fim.model.HashMode.dontHash;
import static org.fim.model.HashMode.hashAll;
import static org.fim.model.HashMode.hashMediumBlock;
import static org.fim.model.HashMode.hashSmallBlock;
import static org.fim.model.Modification.added;
import static org.fim.model.Modification.contentModified;
import static org.fim.model.Modification.copied;
import static org.fim.model.Modification.corrupted;
import static org.fim.model.Modification.dateModified;
import static org.fim.model.Modification.deleted;
import static org.fim.model.Modification.duplicated;
import static org.fim.model.Modification.renamed;
@RunWith(Parameterized.class)
public class StateComparatorTest extends StateAssert {
private HashMode hashMode;
private BuildableContext context;
private BuildableState s1;
private BuildableState s2;
private CompareResult result;
public StateComparatorTest(final HashMode hashMode) {
this.hashMode = hashMode;
}
@Parameters(name = "Hash mode: {0}")
public static Collection<Object[]> parameters() {
return Arrays.asList(new Object[][]{
{dontHash},
{hashSmallBlock},
{hashMediumBlock},
{hashAll}
});
}
@Before
public void setUp() {
context = defaultContext();
context.setHashMode(hashMode);
s1 = new BuildableState(context).addFiles("file_01", "file_02", "file_03", "file_04");
}
@Test
public void canManageSameContent() {
// Set the same file content
s2 = s1.setContent("file_01", "file_01");
result = new StateComparator(context, s1, s2).compare();
assertNothingModified(result);
}
@Test
public void canManageFileAdded() {
s2 = s1.addFiles("file_05");
result = new StateComparator(context, s1, s2).compare();
assertOnlyFilesAdded(result, "file_05");
}
@Test
public void canManageDateModified() {
s2 = s1.touch("file_01");
result = new StateComparator(context, s1, s2).compare();
assertOnlyDatesModified(result, "file_01");
}
@Test
public void noChangeDetectedWhenDatesIgnoredIsSet() {
context.getIgnored().setDatesIgnored(true);
s2 = s1.touch("file_01");
result = new StateComparator(context, s1, s2).compare();
assertNothingModified(result);
}
@Test
public void canManageContentModified() {
s2 = s1.appendContent("file_01", "append_01");
result = new StateComparator(context, s1, s2).compare();
assertOnlyContentModified(result, "file_01");
}
@Test
public void canManageFileRename() {
s2 = s1.rename("file_01", "file_06");
result = new StateComparator(context, s1, s2).compare();
if (hashMode == dontHash) {
assertGotOnlyModifications(result, added, deleted);
assertFilesModified(result, deleted, "file_01");
assertFilesModified(result, added, "file_06");
} else {
assertOnlyFileRenamed(result, new FileNameDiff("file_01", "file_06"));
}
}
@Test
public void noChangeDetectedWhenRenamedIgnoredIsSet() {
context.getIgnored().setRenamedIgnored(true);
s2 = s1.rename("file_01", "file_06");
result = new StateComparator(context, s1, s2).compare();
if (hashMode != dontHash) {
assertNothingModified(result);
}
}
@Test
public void canManageFileCopy() {
s2 = s1.copy("file_01", "file_06");
result = new StateComparator(context, s1, s2).compare();
if (hashMode == dontHash) {
assertOnlyFilesAdded(result, "file_06");
} else {
assertOnlyFileDuplicated(result, new FileNameDiff("file_01", "file_06"));
}
}
@Test
public void canManageFileDelete() {
s2 = s1.delete("file_01");
result = new StateComparator(context, s1, s2).compare();
assertOnlyFileDeleted(result, "file_01");
}
@Test
public void canCopyAFileAndChangeDate() {
s2 = s1.copy("file_01", "file_00")
.copy("file_01", "file_06")
.touch("file_01");
result = new StateComparator(context, s1, s2).compare();
if (hashMode == dontHash) {
assertGotOnlyModifications(result, added, dateModified);
assertFilesModified(result, added, "file_00", "file_06");
} else {
assertGotOnlyModifications(result, duplicated, dateModified);
assertFilesModified(result, duplicated, new FileNameDiff("file_01", "file_00"), new FileNameDiff("file_01", "file_06"));
}
assertFilesModified(result, dateModified, "file_01");
}
@Test
public void canCopyAFileAndChangeContent() {
s2 = s1.copy("file_01", "file_00")
.copy("file_01", "file_06")
.appendContent("file_01", "append_01");
result = new StateComparator(context, s1, s2).compare();
if (hashMode == dontHash) {
assertGotOnlyModifications(result, contentModified, added);
assertFilesModified(result, contentModified, "file_01");
assertFilesModified(result, added, "file_00", "file_06");
} else {
assertGotOnlyModifications(result, copied, contentModified);
assertFilesModified(result, copied, new FileNameDiff("file_01", "file_00"), new FileNameDiff("file_01", "file_06"));
assertFilesModified(result, contentModified, "file_01");
}
}
@Test
public void canCorrectlyDetectRenamedFiles() {
s1 = s1.copy("file_01", "dup_file_01");
s2 = s1.rename("file_01", "new_file_01")
.rename("dup_file_01", "new_dup_file_01");
detectAndAssertRenamedFiles();
}
@Test
public void canCorrectlyDetectRenamedFilesThatHaveDateChanged() {
s1 = s1.copy("file_01", "dup_file_01");
s2 = s1.rename("file_01", "new_file_01").touch("new_file_01")
.rename("dup_file_01", "new_dup_file_01").touch("new_dup_file_01");
detectAndAssertRenamedFiles();
}
private void detectAndAssertRenamedFiles() {
result = new StateComparator(context, s1, s2).compare();
if (hashMode == dontHash) {
assertGotOnlyModifications(result, added, deleted);
assertFilesModified(result, added, "new_file_01", "new_dup_file_01");
assertFilesModified(result, deleted, "file_01", "dup_file_01");
} else {
assertGotOnlyModifications(result, renamed);
assertFilesModified(result, renamed, new FileNameDiff("dup_file_01", "new_file_01"), new FileNameDiff("dup_file_01", "new_dup_file_01"));
}
}
@Test
public void emptyFilesAreNeverSeenAsDuplicates() {
s1 = s1.addEmptyFiles("empty_file_01");
s2 = s1.addEmptyFiles("empty_file_02");
result = new StateComparator(context, s1, s2).compare();
assertGotOnlyModifications(result, added);
assertFilesModified(result, added, "empty_file_02");
}
@Test
public void canDetectHardwareCorruption() {
if (hashMode == dontHash) {
return;
}
s2 = s1.clone();
result = new StateComparator(context, s1, s2).searchForHardwareCorruption().compare();
assertNothingModified(result);
s2 = s2.setContent("file_01", "XXXX");
result = new StateComparator(context, s1, s2).searchForHardwareCorruption().compare();
assertGotOnlyModifications(result, corrupted);
assertFilesModified(result, corrupted, "file_01");
// file_02 is deleted and file_05 is added, they are not detected as corrupted
s2 = s2.delete("file_02").addFiles("file_05");
result = new StateComparator(context, s1, s2).searchForHardwareCorruption().compare();
assertGotOnlyModifications(result, corrupted);
assertFilesModified(result, corrupted, "file_01");
}
@Test
public void withLogDebugWeHaveAResult() {
boolean debugEnabled = Logger.debugEnabled;
try {
Logger.debugEnabled = true;
s2 = s1.clone();
String result = new StateComparator(context, s1, s2).fileStatesToString("My message", s1.getFileStates());
assertThat(result).startsWith(" My message:");
} finally {
Logger.debugEnabled = debugEnabled;
}
}
@Test
public void withoutLogDebugWeHaveNothing() {
boolean debugEnabled = Logger.debugEnabled;
try {
Logger.debugEnabled = false;
s2 = s1.clone();
String result = new StateComparator(context, s1, s2).fileStatesToString("My message", s1.getFileStates());
assertThat(result).isEqualTo("");
} finally {
Logger.debugEnabled = debugEnabled;
}
}
}