在 junit 测试中比较 tar 档案的最佳方法是什么

What is the best way to compare tar archives in junit testing

我正在尝试为一些生成 tar 文件的代码创建 jUnit 测试。在测试期间,我将创建各种 tar 文件并将它们与预期输出的 "Gold" tar 图像进行比较。我一直在努力创建一个 assertTarEquals(String file1, String file2) 函数,并希望有人可以提供有关最佳方法的指导。 tar 文件条目的顺序或属性相同并不重要。我只需要验证它们是否具有所有相同的文件并且这些文件包含相同的内容。我根据此处提供的示例创建了一个 assertZipEquals(String file1, String file2):http://www.java2s.com/Tutorial/Java/0180__File/Comparetwozipfiles.htm 但是 ZipFile.getInputSteam(EntryName) 在 Commons Tar 中似乎没有并行函数类,因为他们还没有在 TarInputStream.

中实现标记

我通常同意单元测试不是测试存档的地方,但被测试的代码管理存档的创建,所以在我看来这不仅是适当的而且是必要的。下面的代码非常难看,我永远不想在生产代码中使用这样的东西,但为了测试我想它没问题....这是我用于 assertArchiveEquals 的代码,它同时支持 tar和 zip 文件....一如既往地欢迎所有反馈。

package com.foo.util.merge;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.io.IOUtils;

import static org.junit.Assert.*;

public final class CompareArchives {

    public static final void assertArchiveEquals(String type, String archive1, String archive2) throws NoSuchAlgorithmException, IOException {
        if (type.endsWith("zip")) {
            assertZipEquals(archive1, archive2);
        } else {
            assertTarEquals(archive1, archive2);
        }
    }

    /**
     * @param archive1
     * @param archive2
     * @throws ZipException 
     * @throws IOException
     */
    public static final void assertZipEquals(String archive1, String archive2) throws ZipException, IOException  {
        // Get Archives
        ZipFile zipFile1 = new ZipFile(new File(archive1));
        ZipFile zipFile2 = new ZipFile(new File(archive2));

        // Get Member Hash
        HashMap<String, ZipEntry> files1 = getMembers(zipFile1);
        HashMap<String, ZipEntry> files2 = getMembers(zipFile2);

        // Compare Files
        assertMembersEqual(zipFile1, files1, zipFile2, files2);
    }

    /**
     * @param archive
     * @return
     * @throws IOException
     */
    private static final HashMap<String, ZipEntry> getMembers(ZipFile archive) throws IOException {
        HashMap<String, ZipEntry> map = new HashMap<String, ZipEntry>();
        @SuppressWarnings("unchecked")
        Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) archive.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            map.put(entry.getName(), entry);
        }
        return map;
    }

    /**
     * @param zip1
     * @param files1
     * @param zip2
     * @param files2
     * @throws IOException
     */
    private static final void assertMembersEqual(ZipFile zip1, HashMap<String, ZipEntry> files1, 
                                                 ZipFile zip2, HashMap<String, ZipEntry> files2) throws IOException {
        if (files1.size() != files2.size()) {
            fail("Different Sizes, expected " + Integer.toString(files1.size()) + " found " + Integer.toString(files2.size()));
        }

        for (String key : files1.keySet()) {
            if (!files2.containsKey(key)) {
                fail("Expected file not in target " + key);
            }
            String file1 = IOUtils.toString(zip1.getInputStream(files1.get(key)));
            String file2 = IOUtils.toString(zip2.getInputStream(files2.get(key)));
            assertEquals(file1, file2);
        }
    }

    /**
     * @param archive1
     * @param archive2
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static final void assertTarEquals(String archive1, String archive2) throws IOException, NoSuchAlgorithmException {
        // Get Member Hash
        HashMap<String, TarArchiveEntry> files1 = getMembers(archive1);
        HashMap<String, TarArchiveEntry> files2 = getMembers(archive2);

        // Compare Files
        assertMembersEqual(archive1, files1, archive2, files2);
    }

    /**
     * @param archive
     * @return
     * @throws IOException
     */
    private static final HashMap<String,TarArchiveEntry> getMembers(String archive) throws IOException {
        TarArchiveInputStream input = new TarArchiveInputStream(
                new BufferedInputStream(
                new FileInputStream(archive)));

        TarArchiveEntry entry;
        HashMap<String, TarArchiveEntry> map = new HashMap<String, TarArchiveEntry>();
        while ((entry = input.getNextTarEntry()) != null) {
            map.put(entry.getName(), entry);
        }
        input.close();
        return map;
    }

    /**
     * @param tar1
     * @param files1
     * @param tar2
     * @param files2
     * @throws IOException
     */
    private static final void assertMembersEqual(String tar1, HashMap<String, TarArchiveEntry> files1, 
                                                 String tar2, HashMap<String, TarArchiveEntry> files2) throws IOException {
        if (files1.size() != files2.size()) {
            fail("Different Sizes, expected " + Integer.toString(files1.size()) + " found " + Integer.toString(files2.size()));
        }

        for (String key : files1.keySet()) {
            if (!files2.containsKey(key)) {
                fail("Expected file not in target " + key);
            }
        }

        for (String key : files1.keySet()) {
            if (!files2.containsKey(key)) {
                fail("Expected file not in target " + key);
            }
        }
        for (String key : files1.keySet()) {
            String file1 = getTarFile(tar1, key);
            String file2 = getTarFile(tar2, key);
            assertEquals(file1, file2);
        }
    }

    /**
     * @param archive
     * @param name
     * @return
     * @throws IOException
     */
    private static final String getTarFile(String archive, String name) throws IOException {
        TarArchiveInputStream input = new TarArchiveInputStream(
                new BufferedInputStream(
                new FileInputStream(archive)));
        TarArchiveEntry entry;
        while ((entry = input.getNextTarEntry()) != null) {
            if (entry.getName().equals(name)) {
                byte[] content = new byte[(int) entry.getSize()];
                input.read(content, 0, content.length);
                input.close();
                return new String(content);
            }
        }
        input.close();
        return "";
    }

}