/*
 * Copyright (c) 2013, Luigi R. Viggiano
 * All rights reserved.
 *
 * This software is distributable under the BSD license.
 * See the terms of the BSD license in the documentation provided with this software.
 */

package org.aeonbits.owner;

import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Properties;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import static org.aeonbits.owner.Util.ignore;
import static org.aeonbits.owner.Util.unreachableButCompilerNeedsThis;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

/**
 * This class contains tests for the {@link Util} class as well utility methods used for test classes.
 *
 * @author Luigi R. Viggiano
 */
public class UtilTest {
    @Test(expected = UnsupportedOperationException.class)
    public void testConstructor() {
        new Util() {
        };
    }

    @Test
    public void testReverse() {
        Integer[] i = {1, 2, 3, 4, 5};
        Integer[] result = Util.reverse(i);
        assertTrue(Arrays.equals(new Integer[] {1, 2, 3, 4, 5}, i));
        assertTrue(Arrays.equals(new Integer[] {5, 4, 3, 2, 1}, result));
    }

    @Test
    public void testIgnore() {
        Object result = ignore();
        assertNull(result);
    }

    @Test
    public void testUnreachable() {
        try {
            unreachableButCompilerNeedsThis();
        } catch(AssertionError err) {
            assertEquals("this code should never be reached", err.getMessage());
        }
    }

    public static void save(File target, Properties p) throws IOException {
        File parent = target.getParentFile();
        parent.mkdirs();
        if (isWindows()) {
            p.store(new FileWriter(target), "saved for test");
        } else {
            File tempFile = File.createTempFile(target.getName(), "temp", parent);
            p.store(new FileWriter(tempFile), "saved for test");
            if (!tempFile.renameTo(target))
                throw new IOException(String.format("Failed to overwrite %s to %s", tempFile.toString(),
                        target.toString()));
        }
    }

    private static boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().indexOf("win") >= 0;
    }

    public static void delete(File target) {
        target.delete();
    }

    public static void saveJar(File file, String entryName, Properties props) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        props.store(out, "saved for test");
        InputStream input = new ByteArrayInputStream(out.toByteArray());
        JarOutputStream output = new JarOutputStream(
                new FileOutputStream(file));
        try {
            ZipEntry entry = new ZipEntry(entryName);
            output.putNextEntry(entry);
            byte[] buffer = new byte[4096];
            int size;
            while ((size = input.read(buffer)) != -1)
                output.write(buffer, 0, size);
        } finally {
            input.close();
            output.close();
        }
    }

    public static void debug(String format, Object... args) {
        if (Boolean.getBoolean("debug"))
            System.out.printf(format, args);
    }

    public static interface MyCloneable extends Cloneable {
        // for some stupid reason java.lang.Cloneable doesn't define this method...
        public Object clone() throws CloneNotSupportedException;
    }

    @SuppressWarnings("unchecked")
    public static <T extends MyCloneable> T[] newArray(int size, T cloneable) throws CloneNotSupportedException {
        Object array = Array.newInstance(cloneable.getClass(), size);
        Array.set(array, 0, cloneable);
        for (int i = 1; i < size; i++)
            Array.set(array, i, cloneable.clone());
        return (T[]) array;
    }

    public static boolean eq(Object o1, Object o2) {
        return Util.eq(o1, o2);
    }

}

@@ -398,35 +398,8 @@
 am;%0A
-import java.io.FileWriter;%0A
 impo
@@ -442,32 +442,61 @@
 io.InputStream;%0A
+import java.io.OutputStream;%0A
 import java.lang
@@ -635,16 +635,59 @@
 Entry;%0A%0A
+import static java.io.File.createTempFile;%0A
 import s
@@ -1734,16 +1734,17 @@
  %7D catch
+ 
 (Asserti
@@ -2034,34 +2034,32 @@
 ) %7B%0A            
-p.
 store(new FileWr
@@ -2060,40 +2060,31 @@
 File
-Writer(target), %22saved for test%22
+OutputStream(target), p
 );%0A 
@@ -2127,21 +2127,16 @@
 pFile = 
-File.
 createTe
@@ -2161,16 +2161,17 @@
 ame(), %22
+.
 temp%22, p
@@ -2190,18 +2190,16 @@
         
-p.
 store(ne
@@ -2208,42 +2208,33 @@
 File
-Writer(tempFile), %22saved for test%22
+OutputStream(tempFile), p
 );%0A 
@@ -2248,21 +2248,23 @@
     
-if (!
+rename(
 tempFile
 .ren
@@ -2263,26 +2263,18 @@
 File
-.renameTo(
+, 
 target)
-)
+;
 %0A   
@@ -2282,159 +2282,139 @@
     
+%7D%0A
     
+%7D%0A%0A
     
-throw new IOException(String.format(%22Failed to overwrite %25s to %25s%22, tempFile.toString(),%0A                        target.toString()));%0A        %7D
+private static void store(OutputStream out, Properties p) throws IOException %7B%0A        p.store(out, %22saved for test%22);
 %0A   
@@ -2658,20 +2658,490 @@
 ar(File 
-file
+target, String entryName, Properties props) throws IOException %7B%0A        File parent = target.getParentFile();%0A        parent.mkdirs();%0A        storeJar(target, entryName, props);%0A    %7D%0A%0A    private static void rename(File source, File target) throws IOException %7B%0A        if (!source.renameTo(target))%0A            throw new IOException(String.format(%22Failed to overwrite %25s to %25s%22, source.toString(), target.toString()));%0A    %7D%0A%0A    private static void storeJar(File target
 , String
@@ -3268,14 +3268,8 @@
     
-props.
 stor
@@ -3275,32 +3275,21 @@
 re(out, 
-%22saved for test%22
+props
 );%0A     
@@ -3409,33 +3409,16 @@
 tStream(
-%0A                
 new File
@@ -3434,12 +3434,14 @@
 eam(
-file
+target
 ));%0A

test refactoring