Initial commit
This commit is contained in:
commit
01c833b44f
5 changed files with 433 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
artist.txt
|
||||||
|
.idea/
|
||||||
|
target/
|
134
automation/pom.xml
Normal file
134
automation/pom.xml
Normal 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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
200
automation/src/main/java/org/usi/sq/util/StringUtils.java
Normal file
200
automation/src/main/java/org/usi/sq/util/StringUtils.java
Normal 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 "{@code \n}",
|
||||||
|
* "{@code \r}", or "{@code \r\n}".</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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue