// Path: src/test/java/at/archistar/TestHelper.java
// public class TestHelper {
// 
//     /** test size for slow-running tests */
//     public static final int REDUCED_TEST_SIZE = 4 * 1024 * 1024;
// 
//     /** test size for normal tests */
//     public static final int TEST_SIZE = 10 * REDUCED_TEST_SIZE;
// 
//     /**
//      * create test data
//      *
//      * @param elementSize fragment size in byte, this will create an array with
//      * elements sized "elementsSize" and a total size of TEST_SIZE
//      * @return test data
//      */
//     public static byte[][] createArray(int elementSize) {
//         return createArray(TEST_SIZE, elementSize);
//     }
// 
//     /**
//      * create test data
//      *
//      * @param size overall test data size
//      * @param elementSize fragment size in byte, this will create an array with
//      * elements sized "elementsSize" and a total size of "size"
//      * @return test data
//      */
//     public static byte[][] createArray(int size, int elementSize) {
//         byte[][] result = new byte[size / elementSize][elementSize];
// 
//         for (int i = 0; i < size / elementSize; i++) {
//             for (int j = 0; j < elementSize; j++) {
//                 result[i][j] = 1;
//             }
//         }
// 
//         return result;
//     }
// 
//     /**
//      * drop the array element at the specified index
//      *
//      * @param shares the array to drop from
//      * @param i the index of the element to drop
//      * @return a new array without the element at the specified index
//      */
//     public static Share[] dropElementAt(Share[] shares, int i) {
//         Share[] res = new Share[shares.length - 1];
//         int pos = 0;
//         for (int x = 0; x < shares.length; x++) {
//             if (x != i) {
//                 res[pos++] = shares[x];
//             }
//         }
//         return res;
//     }
// }
// 
// Path: src/main/java/at/archistar/crypto/data/Share.java
// public interface Share extends Comparable<Share> {
// 
//     /** on-disk version of the share */
//     int VERSION = 5;
// 
//     static void writeMap(DataOutputStream sout, Map<Byte, byte[]> map) throws IOException {
//         sout.writeInt(map.size());
//         for (Map.Entry<Byte, byte[]> e : map.entrySet()) {
//             Byte key = e.getKey();
//             byte[] value = e.getValue();
// 
//             sout.writeByte(key);
//             sout.writeInt(value.length);
//             sout.write(value);
//         }
//     }
// 
//     /**
//      * @return the share's X-value (same as id)
//      */
//     int getX();
// 
//     /**
//      * @return the share's id (same as x-value)
//      */
//     byte getId();
// 
//     /**
//      * @return the share's main body (y-values)
//      */
//     @SuppressFBWarnings("EI_EXPOSE_REP")
//     byte[] getYValues();
// 
//     /**
//      * This returns a serialized form of the content (plus IC info) of the share.
//      *
//      * @return the share's byte[] representation containing all information
//      * @throws IOException
//      */
//     byte[] getSerializedData() throws IOException;
// 
//     /**
//      * This returns a Map of the metadata that are common to all share types;
//      * the idea is that the getMetaData()-implementations in all the share types
//      * first get this Map and then add their own special keys
//      *
//      * @return the metadata that are common to all shares
//      */
//     default HashMap<String, String> getCommonMetaData() {
//         HashMap<String, String> res = new HashMap<>();
//         res.put("archistar-share-type", getShareType());
//         res.put("archistar-version", Integer.toString(VERSION));
//         res.put("archistar-id", Byte.toString(getId()));
//         res.put("archistar-length", Integer.toString(getYValues().length));
//         return res;
//     }
// 
//     /**
//      * @return the (internal) metadata of a share necessary for reconstruction
//      */
//     HashMap<String, String> getMetaData();
// 
//     /**
//      * compare two shares
//      *
//      * @param t the share to be compared
//      * @return +/-1 if different, 0 if same
//      */
//     @Override
//     default int compareTo(Share t) {
// 
//         try {
//             if (Arrays.equals(getSerializedData(), t.getSerializedData())) {
//                 return 0;
//             } else {
//                 return t.getId()- getId();
//             }
//         } catch (IOException ex) {
//             return t.getId() - getId();
//         }
//     }
// 
//     /**
//      * @return a String representation of the type of the share
//      */
//     String getShareType();
// 
//     /**
//      * @return the length of the original file
//      */
//     int getOriginalLength();
// }


import at.archistar.TestHelper;
import at.archistar.crypto.data.BrokenShare;
import at.archistar.crypto.data.Share;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.fest.assertions.api.Assertions.fail;
import org.fest.assertions.core.Condition;
import org.junit.Test;
    public void itFailsWhenThereAreTooFewShares() throws ReconstructionException {
        Share shares[] = algorithm.share(data);
        for (int i = 0; i < k; i++) {
            Share[] shares1 = Arrays.copyOf(shares, i);
            algorithm.reconstruct(shares1);
            fail("too few shares to reconstruct, what was returned?");
        }
    }

    @Test
    public void itStoresAndReconstructsEmptyData() throws ReconstructionException {
        Share[] shares = algorithm.share(new byte[0]);
        Share[] shares2 = algorithm.share(null);

        Condition<Share> broken = new Condition<Share>() {
            @Override
            public boolean matches(Share share) {
                return share instanceof BrokenShare;
            }
        };

        assertThat(shares).isNotEmpty();
        assertThat(shares).areNot(broken);
        assertThat(shares2).isNotEmpty();
        assertThat(shares2).areNot(broken);
        assertThat(algorithm.reconstruct(shares).length).isEqualTo(0);
        assertThat(algorithm.reconstruct(shares2).length).isEqualTo(0);
    }

    @Test
// Path: src/test/java/at/archistar/TestHelper.java
// public class TestHelper {
// 
//     /** test size for slow-running tests */
//     public static final int REDUCED_TEST_SIZE = 4 * 1024 * 1024;
// 
//     /** test size for normal tests */
//     public static final int TEST_SIZE = 10 * REDUCED_TEST_SIZE;
// 
//     /**
//      * create test data
//      *
//      * @param elementSize fragment size in byte, this will create an array with
//      * elements sized "elementsSize" and a total size of TEST_SIZE
//      * @return test data
//      */
//     public static byte[][] createArray(int elementSize) {
//         return createArray(TEST_SIZE, elementSize);
//     }
// 
//     /**
//      * create test data
//      *
//      * @param size overall test data size
//      * @param elementSize fragment size in byte, this will create an array with
//      * elements sized "elementsSize" and a total size of "size"
//      * @return test data
//      */
//     public static byte[][] createArray(int size, int elementSize) {
//         byte[][] result = new byte[size / elementSize][elementSize];
// 
//         for (int i = 0; i < size / elementSize; i++) {
//             for (int j = 0; j < elementSize; j++) {
//                 result[i][j] = 1;
//             }
//         }
// 
//         return result;
//     }
// 
//     /**
//      * drop the array element at the specified index
//      *
//      * @param shares the array to drop from
//      * @param i the index of the element to drop
//      * @return a new array without the element at the specified index
//      */
//     public static Share[] dropElementAt(Share[] shares, int i) {
//         Share[] res = new Share[shares.length - 1];
//         int pos = 0;
//         for (int x = 0; x < shares.length; x++) {
//             if (x != i) {
//                 res[pos++] = shares[x];
//             }
//         }
//         return res;
//     }
// }
// 
// Path: src/main/java/at/archistar/crypto/data/Share.java
// public interface Share extends Comparable<Share> {
// 
//     /** on-disk version of the share */
//     int VERSION = 5;
// 
//     static void writeMap(DataOutputStream sout, Map<Byte, byte[]> map) throws IOException {
//         sout.writeInt(map.size());
//         for (Map.Entry<Byte, byte[]> e : map.entrySet()) {
//             Byte key = e.getKey();
//             byte[] value = e.getValue();
// 
//             sout.writeByte(key);
//             sout.writeInt(value.length);
//             sout.write(value);
//         }
//     }
// 
//     /**
//      * @return the share's X-value (same as id)
//      */
//     int getX();
// 
//     /**
//      * @return the share's id (same as x-value)
//      */
//     byte getId();
// 
//     /**
//      * @return the share's main body (y-values)
//      */
//     @SuppressFBWarnings("EI_EXPOSE_REP")
//     byte[] getYValues();
// 
//     /**
//      * This returns a serialized form of the content (plus IC info) of the share.
//      *
//      * @return the share's byte[] representation containing all information
//      * @throws IOException
//      */
//     byte[] getSerializedData() throws IOException;
// 
//     /**
//      * This returns a Map of the metadata that are common to all share types;
//      * the idea is that the getMetaData()-implementations in all the share types
//      * first get this Map and then add their own special keys
//      *
//      * @return the metadata that are common to all shares
//      */
//     default HashMap<String, String> getCommonMetaData() {
//         HashMap<String, String> res = new HashMap<>();
//         res.put("archistar-share-type", getShareType());
//         res.put("archistar-version", Integer.toString(VERSION));
//         res.put("archistar-id", Byte.toString(getId()));
//         res.put("archistar-length", Integer.toString(getYValues().length));
//         return res;
//     }
// 
//     /**
//      * @return the (internal) metadata of a share necessary for reconstruction
//      */
//     HashMap<String, String> getMetaData();
// 
//     /**
//      * compare two shares
//      *
//      * @param t the share to be compared
//      * @return +/-1 if different, 0 if same
//      */
//     @Override
//     default int compareTo(Share t) {
// 
//         try {
//             if (Arrays.equals(getSerializedData(), t.getSerializedData())) {
//                 return 0;
//             } else {
//                 return t.getId()- getId();
//             }
//         } catch (IOException ex) {
//             return t.getId() - getId();
//         }
//     }
// 
//     /**
//      * @return a String representation of the type of the share
//      */
//     String getShareType();
// 
//     /**
//      * @return the length of the original file
//      */
//     int getOriginalLength();
// }


// Path: src/test/java/at/archistar/crypto/secretsharing/BasicSecretSharingTest.java
import at.archistar.TestHelper;
import at.archistar.crypto.data.BrokenShare;
import at.archistar.crypto.data.Share;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.fest.assertions.api.Assertions.fail;
import org.fest.assertions.core.Condition;
import org.junit.Test;

    public void itFailsWhenThereAreTooFewShares() throws ReconstructionException {
        Share shares[] = algorithm.share(data);
        for (int i = 0; i < k; i++) {
            Share[] shares1 = Arrays.copyOf(shares, i);
            algorithm.reconstruct(shares1);
            fail("too few shares to reconstruct, what was returned?");
        }
    }

    @Test
    public void itStoresAndReconstructsEmptyData() throws ReconstructionException {
        Share[] shares = algorithm.share(new byte[0]);
        Share[] shares2 = algorithm.share(null);

        Condition<Share> broken = new Condition<Share>() {
            @Override
            public boolean matches(Share share) {
                return share instanceof BrokenShare;
            }
        };

        assertThat(shares).isNotEmpty();
        assertThat(shares).areNot(broken);
        assertThat(shares2).isNotEmpty();
        assertThat(shares2).areNot(broken);
        assertThat(algorithm.reconstruct(shares).length).isEqualTo(0);
        assertThat(algorithm.reconstruct(shares2).length).isEqualTo(0);
    }

    @Test
    public void itRecoversMissingShares() throws ReconstructionException {