commit 01c833b44fca65545ff884f98d624853afafa55e Author: Claudio Maggioni Date: Wed Mar 1 16:20:17 2023 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1ad9fff --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +artist.txt +.idea/ +target/ diff --git a/automation/pom.xml b/automation/pom.xml new file mode 100644 index 0000000..d5d58a2 --- /dev/null +++ b/automation/pom.xml @@ -0,0 +1,134 @@ + + + 4.0.0 + + org.usi.sq + sq-2021-1 + 1.0 + + UTF-8 + 1.7.0-M1 + 5.6.2 + 5.6.2 + 4.13 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 8 + 8 + + + + org.jacoco + jacoco-maven-plugin + 0.8.5 + + + + prepare-agent + + + + + report + test + + report + + + + + + org.pitest + pitest-maven + 1.5.2 + + + org.usi.sq* + + + org.usi.sq* + * + + + + + org.pitest + pitest-junit5-plugin + 0.12 + + + + + + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + junit + junit + ${junit.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit.vintage.version} + test + + + + + + org.jacoco + jacoco-maven-plugin + + + + + report + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 3.0.0-M5 + + + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.1 + + + + + + diff --git a/automation/src/main/java/org/usi/sq/util/CollectionUtils.java b/automation/src/main/java/org/usi/sq/util/CollectionUtils.java new file mode 100644 index 0000000..8fbd65f --- /dev/null +++ b/automation/src/main/java/org/usi/sq/util/CollectionUtils.java @@ -0,0 +1,71 @@ +package org.usi.sq.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CollectionUtils { + + private static final double EPSILON = 1e-6; + + /** + * Implementation of insertion sort. Insertion sort can be used in cases + * where the input list is almost sorted or small. The list implementation + * should provide fast indexed access. Due to its quadratic worst-case + * runtime complexity, other sorting algorithms should be used in the + * general case. + * + * @param list the list to be sorted in-place + * @param the type of the elements in the list (need to be comparable) + * @throws IllegalArgumentException if called with null pointer + */ + static > void sort(List list){ + if(list == null) + throw new IllegalArgumentException("Sort must not be called with " + + "null"); + for(int i = 1; i < list.size(); i++){ + T key = list.get(i); + int j = 0; + for(j = i-1; j >= 0; j--){ + T elem = list.get(j); + if(elem.compareTo(key) > 0){ // check if elem > key + list.set(j+1, elem); + } else{ + break; + } + } + list.set(j+1,key); + } + } + + /** + * This method computes the arithmetic mean of values in a subarray of + * the array passed as an argument. It returns {@code Double.NaN} if the + * length of the subarray is zero. + * + * @param values values for which the mean should be computed + * @param begin the first of the considered subarray + * @param length the length of the subarray + * @return the arithmetic mean or {@code Double.NaN} if length is zero + * @throws IllegalArgumentException if values is null or the subarray length + * exceeds the length of the array {@code values} + */ + public static double mean(int[] values, int begin, int length){ + if(length == 0) + return Double.NaN; + if(values == null) + throw new IllegalArgumentException("mean must not be called with " + + "null."); + if(begin + length > values.length) + throw new IllegalArgumentException("Boundary mismatch: the " + + "specified length of the subarray exceeds the length of " + + "the array."); + int sum = 0; + for (int i = begin; i < begin + length; i++){ + sum += values[i]; + } + double mean = (double)sum/length; + return mean; + } + +} diff --git a/automation/src/main/java/org/usi/sq/util/StringUtils.java b/automation/src/main/java/org/usi/sq/util/StringUtils.java new file mode 100644 index 0000000..816b668 --- /dev/null +++ b/automation/src/main/java/org/usi/sq/util/StringUtils.java @@ -0,0 +1,200 @@ +package org.usi.sq.util; + +import java.util.*; + +public class StringUtils { + + + private static final String EMPTY = ""; + private static final Map HEX_VALUES = new HashMap<>(); + static { + HEX_VALUES.put('0', 0); + HEX_VALUES.put('1', 1); + HEX_VALUES.put('2', 2); + HEX_VALUES.put('3', 3); + HEX_VALUES.put('4', 4); + HEX_VALUES.put('5', 5); + HEX_VALUES.put('6', 6); + HEX_VALUES.put('7', 7); + HEX_VALUES.put('8', 8); + HEX_VALUES.put('9', 9); + HEX_VALUES.put('A', 10); + HEX_VALUES.put('B', 11); + HEX_VALUES.put('C', 12); + HEX_VALUES.put('D', 13); + HEX_VALUES.put('E', 14); + HEX_VALUES.put('F', 15); + HEX_VALUES.put('a', 10); + HEX_VALUES.put('b', 11); + HEX_VALUES.put('c', 12); + HEX_VALUES.put('d', 13); + HEX_VALUES.put('e', 14); + HEX_VALUES.put('f', 15); + } + + /** + * The implementation of this method has been adapted from StringUtils in + * Apache Commons Lang. The following documentation is taken from the + * original implementation. + * + *

Removes one newline from end of a String if it's there, + * otherwise leave it alone. A newline is "{@code \n}", + * "{@code \r}", or "{@code \r\n}".

+ * + *

NOTE: This method changed in 2.0. + * It now more closely matches Perl chomp.

+ * + *
+     * StringUtils.chomp(null)          = null
+     * StringUtils.chomp("")            = ""
+     * StringUtils.chomp("abc \r")      = "abc "
+     * StringUtils.chomp("abc\n")       = "abc"
+     * StringUtils.chomp("abc\r\n")     = "abc"
+     * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
+     * StringUtils.chomp("abc\n\r")     = "abc\n"
+     * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
+     * StringUtils.chomp("\r")          = ""
+     * StringUtils.chomp("\n")          = ""
+     * StringUtils.chomp("\r\n")        = ""
+     * 
+ * + * @param str the String to chomp a newline from, may be null + * @return String without newline, {@code null} if null String input + */ + public static String chomp(final String str) { + if (str == null || str.isEmpty()) { + return str; + } + + if (str.length() == 1) { + final char ch = str.charAt(0); + if (ch == '\r' || ch == '\n') { + return EMPTY; + } + return str; + } + + int lastIdx = str.length() - 1; + final char last = str.charAt(lastIdx); + + if (last == '\n') { + if (str.charAt(lastIdx - 1) == '\r') { + lastIdx--; + } + } else if (last != '\r') { + lastIdx++; + } + return str.substring(0, lastIdx); + } + + /** + * The implementation of this method has been adapted from StringUtils in + * Apache Commons Lang. + * The following documentation has been slightly adapted from the original documentation. + * + *

Joins the string representations of the elements in the provided {@code List} + * into a single String containing the provided list of elements. The string representation + * of an element is retrieved via {@code Object.toString()}.

+ * + *

No delimiter is added before or after the list. + * Null objects or empty strings within the array are represented by + * empty strings.

+ * + *
+     * StringUtils.join(null, *)               = null
+     * StringUtils.join([], *)                 = ""
+     * StringUtils.join([null], *)             = ""
+     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
+     * StringUtils.join(["a", "b", "c"], null) = "abc"
+     * StringUtils.join([null, "", "a"], ';')  = ";;a"
+     * 
+ * + * @param list the {@code List} of values to join together, may be null + * @param separator the separator character to use + * @param startIndex the first index to start joining from. It is + * an error to pass in a start index past the end of the list + * @param endIndex the index to stop joining from (exclusive). It is + * an error to pass in an end index past the end of the list + * @return the joined String, {@code null} if null list input + * @since 3.8 + */ + public static String join(final List list, final String separator, final int startIndex, final int endIndex) { + if (list == null) { + return null; + } + final int noOfItems = endIndex - startIndex; + if (noOfItems <= 0) { + return EMPTY; + } + final List subList = list.subList(startIndex, endIndex); + return join(subList.iterator(), separator); + } + public static String join(final Iterator iterator, final String separator) { + + // handle null, zero and one elements before building a buffer + if (iterator == null) { + return null; + } + if (!iterator.hasNext()) { + return EMPTY; + } + final Object first = iterator.next(); + if (!iterator.hasNext()) { + return Objects.toString(first, ""); + } + + // two or more elements + final StringBuilder buf = new StringBuilder(); + if (first != null) { + buf.append(first); + } + + while (iterator.hasNext()) { + if (separator != null) { + buf.append(separator); + } + final Object obj = iterator.next(); + if (obj != null) { + buf.append(obj); + } + } + return buf.toString(); + } + + /** + * This is a reimplementation of the C function cgi_decode presented in + * "Software Testing and Analysis: Process, Principles, and Techniques" by + * Pezzè and Young. + * It decodes a CGI-encoded string. For more information, please refer to the original + * implementation. + * + * @param encoded a CGI-encoded string + * @return {@code Optional.empty()} in case of an error (malformed input), + * otherwise {@code Optional.of(result)}, where result is the decoded string + */ + public static Optional cgiDecode(String encoded){ + StringBuilder decodedBuilder = new StringBuilder(); + boolean ok = true; + for(int encodedI = 0; encodedI < encoded.length(); encodedI++){ + char c = encoded.charAt(encodedI); + if(c == '+'){ + decodedBuilder.append(' '); + } else if(c == '%'){ + Integer digitHigh = HEX_VALUES.get(encoded.charAt(++encodedI)); + Integer digitLow = HEX_VALUES.get(encoded.charAt(++encodedI)); + if(digitHigh == null || digitLow == null){ + ok = false; + } else { + decodedBuilder.append((char)(16*digitHigh + digitLow)); + } + } else { + decodedBuilder.append(c); + } + } + if(ok){ + return Optional.of(decodedBuilder.toString()); + } else { + return Optional.empty(); + } + } +} diff --git a/automation/src/test/java/org/usi/sq/util/CollectionUtilsTest.java b/automation/src/test/java/org/usi/sq/util/CollectionUtilsTest.java new file mode 100644 index 0000000..d3190bb --- /dev/null +++ b/automation/src/test/java/org/usi/sq/util/CollectionUtilsTest.java @@ -0,0 +1,25 @@ +package org.usi.sq.util; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + + +class CollectionUtilsTest { + private static final double EPSILON = 1e-6; + + @Test + void testMean_Normal() { + int[] values = new int[]{1,2,3,4}; + + double actual = CollectionUtils.mean(values,0,4); + assertEquals(2.5, actual, EPSILON); + } + + @Test + void testMean_ZeroLength() { + int[] values = new int[]{1,2,3,4}; + + double actual = CollectionUtils.mean(values,0,0); + assertEquals(Double.NaN, actual, EPSILON); + } +}