This is an automated email from the ASF dual-hosted git repository. rouazana pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit c7a98909d58375deeef47389b453007b48b65bb8 Author: Tran Tien Duc <[email protected]> AuthorDate: Mon Mar 25 15:34:07 2019 +0700 JAMES-2688 ZipAssert `hasSameContentWith` impl --- .../org/apache/james/mailbox/backup/ZipAssert.java | 96 +++++++- .../apache/james/mailbox/backup/ZipAssertTest.java | 256 +++++++++++++++++---- 2 files changed, 306 insertions(+), 46 deletions(-) diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java index 7c46fad..9f0c9b0 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssert.java @@ -20,13 +20,17 @@ package org.apache.james.mailbox.backup; import static org.apache.james.mailbox.backup.ZipArchiveEntryAssert.assertThatZipEntry; +import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.stream.Stream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipExtraField; @@ -34,8 +38,10 @@ import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import org.assertj.core.api.AbstractAssert; import org.assertj.core.error.BasicErrorMessageFactory; +import org.assertj.core.error.ErrorMessageFactory; import com.github.steveash.guavate.Guavate; +import com.google.common.collect.ImmutableList; public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> implements AutoCloseable { interface EntryCheck { @@ -77,7 +83,7 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> implements Aut } } - static ZipAssert assertThatZip(ZipFile zipFile) { + public static ZipAssert assertThatZip(ZipFile zipFile) { return new ZipAssert(zipFile); } @@ -93,6 +99,29 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> implements Aut return new BasicErrorMessageFactory("%nExpecting %s to be empty", zipFile); } + private static BasicErrorMessageFactory shouldBeNonNull() { + return new BasicErrorMessageFactory("%nExpecting zipFile to be non-null"); + } + + private static BasicErrorMessageFactory shouldHaveSameEntriesSize(List<ZipArchiveEntry> entries, List<ZipArchiveEntry> expectedEntries) { + return new BasicErrorMessageFactory("%nExpecting zipFile entries has size (%s) but actually (%s)", expectedEntries.size(), entries.size()); + } + + private static ErrorMessageFactory entriesShouldHaveSameContentAt(int entryIndex, String entryContentAssertionError) { + return new BasicErrorMessageFactory("%nExpecting zipFile entry at index %s have same content. Details: \n%s", + entryIndex, entryContentAssertionError); + } + + private static ErrorMessageFactory entriesShouldHaveSameName(ZipArchiveEntry entry, ZipArchiveEntry expectedEntry, int entryIndex) { + return new BasicErrorMessageFactory("%nExpecting zipFile entry name (%s) at index %s but actually (%s)", + expectedEntry.getName(), entryIndex, entry.getName()); + } + + private static ErrorMessageFactory entriesShouldHaveSameExtraFields(ZipArchiveEntry entry, ZipArchiveEntry expectedEntry, int entryIndex) { + return new BasicErrorMessageFactory("%nExpecting zipFile entry at index %s has extra fields (%s) but actually (%s)", entryIndex, + expectedEntry.getExtraFields(), entry.getExtraFields()); + } + private final ZipFile zipFile; private ZipAssert(ZipFile zipFile) { @@ -130,4 +159,69 @@ public class ZipAssert extends AbstractAssert<ZipAssert, ZipFile> implements Aut public void close() throws Exception { zipFile.close(); } + + public ZipAssert hasSameContentWith(ZipFile anotherZipFile) throws IOException { + validateNonNull(zipFile); + validateNonNull(anotherZipFile); + + ArrayList<ZipArchiveEntry> entries = Collections.list(zipFile.getEntries()); + ArrayList<ZipArchiveEntry> entriesOfAnother = Collections.list(anotherZipFile.getEntries()); + + if (entries.size() != entriesOfAnother.size()) { + throwAssertionError(shouldHaveSameEntriesSize(entries, entriesOfAnother)); + } + + for (int entryIndex = 0; entryIndex < entries.size(); entryIndex++) { + ZipArchiveEntry entry = entries.get(entryIndex); + ZipArchiveEntry entryOfAnother = entriesOfAnother.get(entryIndex); + haveSameName(entry, entryOfAnother, entryIndex); + haveSameExtraFields(entry, entryOfAnother, entryIndex); + haveSameContentAt(zipFile.getInputStream(entry), anotherZipFile.getInputStream(entryOfAnother), entryIndex); + } + + return myself; + } + + private void haveSameName(ZipArchiveEntry entry, ZipArchiveEntry expectedEntry, int entryIndex) { + try { + assertThat(entry.getName()).isEqualTo(expectedEntry.getName()); + } catch (AssertionError assertionError) { + throwAssertionError(entriesShouldHaveSameName(entry, expectedEntry, entryIndex)); + } + } + + private void haveSameExtraFields(ZipArchiveEntry entry, ZipArchiveEntry expectedEntry, int entryIndex) { + try { + assertThat(extractJamesExtraFields(entry)) + .containsExactlyElementsOf(extractJamesExtraFields(expectedEntry)); + } catch (AssertionError assertionError) { + throwAssertionError(entriesShouldHaveSameExtraFields(entry, expectedEntry, entryIndex)); + } + } + + private void haveSameContentAt(InputStream entryContent, InputStream expectingEntryContent, int entryIndex) { + try { + assertThat(entryContent) + .hasSameContentAs(expectingEntryContent); + } catch (AssertionError assertionError) { + throwAssertionError(entriesShouldHaveSameContentAt(entryIndex, assertionError.getMessage())); + } + } + + private void validateNonNull(ZipFile zipFile) { + if (zipFile == null) { + throwAssertionError(shouldBeNonNull()); + } + } + + /** + * Because there are always some extra fields not belong to James, and their equals() method doesn't work + * @param entry + * @return + */ + private ImmutableList<ZipExtraField> extractJamesExtraFields(ZipArchiveEntry entry) { + return Stream.of(entry.getExtraFields()) + .filter(field -> field instanceof WithZipHeader) + .collect(Guavate.toImmutableList()); + } } diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java index 4e391fa..b000831 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipAssertTest.java @@ -21,26 +21,81 @@ package org.apache.james.mailbox.backup; import static org.apache.james.mailbox.backup.ZipAssert.EntryChecks.hasName; import static org.apache.james.mailbox.backup.ZipAssert.assertThatZip; +import static org.apache.james.mailbox.backup.ZipAssertTest.ZipEntryWithContent.entryBuilder; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.AbstractMap.SimpleImmutableEntry; import org.apache.commons.compress.archivers.zip.ExtraFieldUtils; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipExtraField; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.io.IOUtils; import org.apache.james.junit.TemporaryFolderExtension; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.testcontainers.shaded.com.google.common.collect.ImmutableList; @ExtendWith(TemporaryFolderExtension.class) public class ZipAssertTest { + + static class ZipEntryWithContent { + + static class Builder { + @FunctionalInterface + interface RequireName { + RequireContent name(String name); + } + + @FunctionalInterface + interface RequireContent { + ReadyToBuild content(byte[] content); + } + + static class ReadyToBuild { + private final String name; + private final byte[] content; + private final ImmutableList.Builder<ZipExtraField> extraFieldBuilder; + + ReadyToBuild(String name, byte[] content) { + this.name = name; + this.content = content; + this.extraFieldBuilder = new ImmutableList.Builder<>(); + } + + ReadyToBuild addField(ZipExtraField zipExtraField) { + extraFieldBuilder.add(zipExtraField); + return this; + } + + public ZipEntryWithContent build() { + return new ZipEntryWithContent(name, new ByteArrayInputStream(content), extraFieldBuilder.build()); + } + } + } + + static Builder.RequireName entryBuilder() { + return name -> content -> new Builder.ReadyToBuild(name, content); + } + + private final String name; + private final InputStream content; + private final ImmutableList<ZipExtraField> extraFields; + + ZipEntryWithContent(String name, InputStream content, ImmutableList<ZipExtraField> extraFields) { + this.name = name; + this.content = content; + this.extraFields = extraFields; + } + } private static final String ENTRY_NAME = "entryName"; private static final String ENTRY_NAME_2 = "entryName2"; private static final String DIRECTORY_NAME = "folder/"; @@ -53,32 +108,35 @@ public class ZipAssertTest { private static final SimpleImmutableEntry<String, byte[]> ENTRY = new SimpleImmutableEntry<>(ENTRY_NAME, ENTRY_CONTENT); private static final SimpleImmutableEntry<String, byte[]> ENTRY_2 = new SimpleImmutableEntry<>(ENTRY_NAME_2, ENTRY_CONTENT_2); private File destination; + private File destination2; @BeforeEach void beforeEach(TemporaryFolderExtension.TemporaryFolder temporaryFolder) throws Exception { destination = File.createTempFile("backup-test", ".zip", temporaryFolder.getTempDir()); + destination2 = File.createTempFile("backup-test2", ".zip", temporaryFolder.getTempDir()); ExtraFieldUtils.register(SizeExtraField.class); + ExtraFieldUtils.register(UidExtraField.class); } @SafeVarargs - private final void buildZipFile(SimpleImmutableEntry<String, byte[]>... entries) throws Exception { + private final ZipFile buildZipFile(SimpleImmutableEntry<String, byte[]>... entries) throws Exception { try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { - for (SimpleImmutableEntry<String, byte[]> entry : entries) { - ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File("any"), entry.getKey()); - archiveOutputStream.putArchiveEntry(archiveEntry); - IOUtils.copy(new ByteArrayInputStream(entry.getValue()), archiveOutputStream); - archiveOutputStream.closeArchiveEntry(); + for (SimpleImmutableEntry<String, byte[]> entry : entries) { + ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File("any"), entry.getKey()); + archiveOutputStream.putArchiveEntry(archiveEntry); + IOUtils.copy(new ByteArrayInputStream(entry.getValue()), archiveOutputStream); + archiveOutputStream.closeArchiveEntry(); } archiveOutputStream.finish(); } + + return new ZipFile(destination); } @Test public void hasNoEntryShouldNotThrowWhenEmpty() throws Exception { - buildZipFile(); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile()) { assertThatCode(() -> assertThatZip(zipFile) .hasNoEntry()) .doesNotThrowAnyException(); @@ -87,9 +145,7 @@ public class ZipAssertTest { @Test public void hasNoEntryShouldThrowWhenNotEmpty() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatThrownBy(() -> assertThatZip(zipFile) .hasNoEntry()) .isInstanceOf(AssertionError.class); @@ -98,9 +154,7 @@ public class ZipAssertTest { @Test public void containsExactlyEntriesMatchingShouldNotThrowWhenBothEmpty() throws Exception { - buildZipFile(); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile()) { assertThatCode(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching()) .doesNotThrowAnyException(); @@ -109,9 +163,7 @@ public class ZipAssertTest { @Test public void containsExactlyEntriesMatchingShouldNotThrowWhenRightOrder() throws Exception { - buildZipFile(ENTRY, ENTRY_2); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY, ENTRY_2)) { assertThatCode(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME), @@ -122,9 +174,7 @@ public class ZipAssertTest { @Test public void hasNameShouldThrowWhenWrongName() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME_2))) @@ -134,9 +184,7 @@ public class ZipAssertTest { @Test public void isDirectoryShouldThrowWhenNotADirectory() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME) @@ -166,9 +214,7 @@ public class ZipAssertTest { @Test public void containsExactlyEntriesMatchingShouldNotThrowWhenWrongOrder() throws Exception { - buildZipFile(ENTRY, ENTRY_2); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY, ENTRY_2)) { assertThatCode(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME), @@ -179,9 +225,7 @@ public class ZipAssertTest { @Test public void containsExactlyEntriesMatchingShouldThrowWhenExpectingMoreEntries() throws Exception { - buildZipFile(ENTRY, ENTRY_2); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY, ENTRY_2)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME), @@ -193,9 +237,7 @@ public class ZipAssertTest { @Test public void containsExactlyEntriesMatchingShouldThrowWhenExpectingLessEntries() throws Exception { - buildZipFile(ENTRY, ENTRY_2); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY, ENTRY_2)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME))) @@ -205,9 +247,7 @@ public class ZipAssertTest { @Test public void hasStringContentShouldNotThrowWhenIdentical() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatCode(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME) @@ -218,9 +258,7 @@ public class ZipAssertTest { @Test public void hasStringContentShouldThrowWhenDifferent() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME) @@ -231,9 +269,7 @@ public class ZipAssertTest { @Test public void containsExactlyExtraFieldsShouldNotThrowWhenBothEmpty() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatCode(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME) @@ -244,9 +280,7 @@ public class ZipAssertTest { @Test public void containsExactlyExtraFieldsShouldThrowWhenMissingExpectedField() throws Exception { - buildZipFile(ENTRY); - - try (ZipFile zipFile = new ZipFile(destination)) { + try (ZipFile zipFile = buildZipFile(ENTRY)) { assertThatThrownBy(() -> assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(ENTRY_NAME) @@ -298,4 +332,136 @@ public class ZipAssertTest { .doesNotThrowAnyException(); } } + + @Nested + class HasSameContentTest { + + @Test + void hasSameContentShouldThrowWhenExpectedZipFileIsNull() throws Exception { + try (ZipFile assertedZipFile = zipFile(destination, entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT).build())) { + ZipFile expectedZipFile = null; + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenAssertedZipFileIsNull() throws Exception { + try (ZipFile expectedZipFile = zipFile(destination, entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT).build())) { + ZipFile assertedZipFile = null; + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenAssertedZipFileHasDifferentSizeWithExpectedZipFile() throws Exception { + ZipEntryWithContent sameEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT).build(); + ZipEntryWithContent additionalEntry = entryBuilder().name(ENTRY_NAME_2).content(ENTRY_CONTENT).build(); + + try (ZipFile expectedZipFile = zipFile(destination, sameEntry); + ZipFile assertedZipFile = zipFile(destination2, sameEntry, additionalEntry)) { + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenAssertedEntriesHaveDifferentContent() throws Exception { + try (ZipFile expectedZipFile = zipFile(destination, entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT).build()); + ZipFile assertedZipFile = zipFile(destination2, entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT_2).build())) { + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenAssertedEntriesHaveDifferentNames() throws Exception { + try (ZipFile expectedZipFile = zipFile(destination, entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT).build()); + ZipFile assertedZipFile = zipFile(destination2, entryBuilder().name(ENTRY_NAME_2).content(ENTRY_CONTENT).build())) { + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenEntryHasDifferentExtraFieldsSize() throws Exception { + ZipEntryWithContent expectedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new UidExtraField(1L)) + .addField(new UidExtraField(2L)) + .build(); + + ZipEntryWithContent assertedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new UidExtraField(1L)) + .build(); + + try (ZipFile expectedZipFile = zipFile(destination, expectedEntry); + ZipFile assertedZipFile = zipFile(destination2, assertedEntry)) { + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenEntryHasSameExtraFieldsSizeButDifferentOrder() throws Exception { + ZipEntryWithContent expectedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new UidExtraField(1L)) + .addField(new SizeExtraField(2L)) + .build(); + + ZipEntryWithContent assertedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new SizeExtraField(2L)) + .addField(new UidExtraField(1L)) + .build(); + + try (ZipFile expectedZipFile = zipFile(destination, expectedEntry); + ZipFile assertedZipFile = zipFile(destination2, assertedEntry)) { + assertThatThrownBy(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .isInstanceOf(AssertionError.class); + } + } + + @Test + void hasSameContentShouldThrowWhenEntryHasSameExtraFieldsSizeAndOrder() throws Exception { + ZipEntryWithContent expectedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new UidExtraField(1L)) + .addField(new SizeExtraField(2L)) + .build(); + + ZipEntryWithContent assertedEntry = entryBuilder().name(ENTRY_NAME).content(ENTRY_CONTENT) + .addField(new UidExtraField(1L)) + .addField(new SizeExtraField(2L)) + .build(); + + try (ZipFile expectedZipFile = zipFile(destination, expectedEntry); + ZipFile assertedZipFile = zipFile(destination2, assertedEntry)) { + assertThatCode(() -> assertThatZip(assertedZipFile) + .hasSameContentWith(expectedZipFile)) + .doesNotThrowAnyException(); + } + } + + private ZipFile zipFile(File destination, ZipEntryWithContent...entries) throws Exception { + try (ZipArchiveOutputStream archiveOutputStream = new ZipArchiveOutputStream(destination)) { + for (ZipEntryWithContent entry : entries) { + ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File("any"), entry.name); + entry.extraFields. + forEach(archiveEntry::addExtraField); + archiveOutputStream.putArchiveEntry(archiveEntry); + IOUtils.copy(entry.content, archiveOutputStream); + archiveOutputStream.closeArchiveEntry(); + } + archiveOutputStream.finish(); + } + + return new ZipFile(destination); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
