package com.github.cstroe.svndumpgui.internal;

import com.github.cstroe.svndumpgui.api.SvnDump;
import com.github.cstroe.svndumpgui.api.SvnDumpWriter;
import com.github.cstroe.svndumpgui.generated.ParseException;
import junit.framework.ComparisonFailure;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

public class SvnDumpWriterImplTest {

    @Test
    public void write_empty_dump() throws ParseException, IOException {
        recreateDumpFile("dumps/empty.dump");
    }

    @Test
    public void write_dump_with_one_commit() throws ParseException, IOException {
        recreateDumpFile("dumps/firstcommit.dump");
    }

    @Test
    public void write_dump_with_file_content() throws ParseException, IOException {
        recreateDumpFile("dumps/add_file.dump");
    }

    @Test
    public void write_dump_with_different_node_order() throws ParseException, IOException {
        recreateDumpFile("dumps/different_node_order.dump");
    }

    @Test
    public void write_dump_with_different_node_order2() throws ParseException, IOException {
        recreateDumpFile("dumps/different_node_order2.dump");
    }

    @Test
    public void write_dump_with_optional_node_properties() throws ParseException, IOException {
        recreateDumpFile("dumps/add_file_no_node_properties.dump");
    }

    @Test
    public void write_dump_with_binary_file_commit() throws ParseException, IOException {
        recreateDumpFile("dumps/binary_commit.dump");
    }

    @Test
    public void write_dump_rename() throws ParseException, IOException {
        recreateDumpFile("dumps/svn_rename.dump");
    }

    @Test
    public void write_no_copy_hashes() throws ParseException, IOException {
        recreateDumpFile("dumps/svn_rename_no_copy_hashes.dump");
    }

    @Test
    public void write_directory_nodes() throws ParseException, IOException {
        recreateDumpFile("dumps/svn_add_directory.dump");
    }

    private void recreateDumpFile(String dumpFile) throws ParseException, IOException {
        SvnDump dump = SvnDumpFileParserTest.parse(dumpFile);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        SvnDumpWriter dumpWriter = new SvnDumpWriterImpl();

        dumpWriter.write(baos, dump);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        InputStream s = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream(dumpFile);

        assertEqual(s, bais);
    }

    // adapted from: http://stackoverflow.com/questions/4245863
    private void assertEqual(InputStream expectedStream, InputStream actualStream) throws IOException {
        byte[] buf1 = new byte[64 *1024];
        byte[] buf2 = new byte[64 *1024];
        boolean readingD2 = false;
        try {
            DataInputStream d2 = new DataInputStream(actualStream);
            long filePosition = 0;
            int len;
            while ((len = expectedStream.read(buf1)) > 0) {
                readingD2 = true;
                d2.readFully(buf2,0,len);
                readingD2 = false;
                for(int i=0;i<len;i++, filePosition++)
                    if(buf1[i] != buf2[i]) {
                        throw new ComparisonFailure("Streams differ." + buf1[i] + " != " + buf2[i], new String(buf1), new String(buf2));
                    }
            }
            int d2r = d2.read();
            if(!(d2r < 0)) { // is the end of the second file also?
                throw new ComparisonFailure("Actual stream is shorter than expected. (The extra character is tacked on at the end)",
                        new String(buf1), new String(buf2) + String.valueOf((char)d2r));
            }
        } catch(EOFException ioe) {
            if(!readingD2) {
                throw new ComparisonFailure("Actual stream is longer than expected.", new String(buf1), new String(buf2));
            } else {
                throw new ComparisonFailure("Actual stream is shorter than expected.", new String(buf1), new String(buf2));
            }
        } finally {
            expectedStream.close();
            actualStream.close();
        }
    }
}
@@ -2072,24 +2072,171 @@
 p%22);%0A    %7D%0A%0A
+    @Test%0A    public void write_delete_nodes() throws ParseException, IOException %7B%0A        recreateDumpFile(%22dumps/svn_delete_file.dump%22);%0A    %7D%0A%0A
     private 

Test parsing a delete node.