Initial commit

This commit is contained in:
Claudio Maggioni 2023-03-01 16:20:17 +01:00
commit 01c833b44f
5 changed files with 433 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
artist.txt
.idea/
target/

134
automation/pom.xml Normal file
View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.usi.sq</groupId>
<artifactId>sq-2021-1</artifactId>
<version>1.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.platform.version>1.7.0-M1</junit.platform.version>
<junit.jupiter.version>5.6.2</junit.jupiter.version>
<junit.vintage.version>5.6.2</junit.vintage.version>
<junit.version>4.13</junit.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<!-- attached to Maven test phase -->
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.pitest</groupId>
<artifactId>pitest-maven</artifactId>
<version>1.5.2</version>
<configuration>
<targetClasses>
<param>org.usi.sq*</param>
</targetClasses>
<targetTests>
<param>org.usi.sq*</param>
<param>*</param>
</targetTests>
</configuration>
<dependencies>
<dependency>
<groupId>org.pitest</groupId>
<artifactId>pitest-junit5-plugin</artifactId>
<version>0.12</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<reportSets>
<reportSet>
<reports>
<!-- select non-aggregate reports -->
<report>report</report>
</reports>
</reportSet>
</reportSets>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<!-- place configuration here if required-->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.1</version>
</plugin>
</plugins>
</reporting>
</project>

View File

@ -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 <T> the type of the elements in the list (need to be comparable)
* @throws IllegalArgumentException if called with null pointer
*/
static <T extends Comparable<T>> void sort(List<T> 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;
}
}

View File

@ -0,0 +1,200 @@
package org.usi.sq.util;
import java.util.*;
public class StringUtils {
private static final String EMPTY = "";
private static final Map<Character, Integer > 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.
*
* <p>Removes one newline from end of a String if it's there,
* otherwise leave it alone. A newline is &quot;{@code \n}&quot;,
* &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.</p>
*
* <p>NOTE: This method changed in 2.0.
* It now more closely matches Perl chomp.</p>
*
* <pre>
* 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") = ""
* </pre>
*
* @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.
*
* <p>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()}.</p>
*
* <p>No delimiter is added before or after the list.
* Null objects or empty strings within the array are represented by
* empty strings.</p>
*
* <pre>
* 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"
* </pre>
*
* @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<String> 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();
}
}
}

View File

@ -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);
}
}