Skip to content

Commit 81d7bd1

Browse files
authored
Moves summary tests to the separate module and fix bug with empty summary generation for the Stats.of (#239)
* Added the initial solution for the bug fix * Disabled tests * Disabled integration tests * Removed comments * Added comments and renamed methods * Renamed method * Fixed test after the method renaming * Fixed the regular expression
1 parent a20b078 commit 81d7bd1

File tree

14 files changed

+454
-34
lines changed

14 files changed

+454
-34
lines changed

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ include 'utbot-instrumentation-tests'
1616
include 'utbot-summary'
1717
include 'utbot-gradle'
1818
include 'utbot-maven'
19+
include 'utbot-summary-tests'
1920

utbot-analytics/build.gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ configurations {
55
mlmodels
66
}
77

8-
98
def osName = System.getProperty('os.name').toLowerCase().split()[0]
109
if (osName == "mac") osName = "macosx"
1110
String classifier = osName + "-x86_64"
@@ -49,11 +48,9 @@ dependencies {
4948
}
5049

5150
test {
52-
5351
useJUnitPlatform {
5452
excludeTags 'Summary'
5553
}
56-
5754
}
5855

5956
processResources {
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (C) 2012 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package guava.examples.math;
16+
17+
import java.io.Serializable;
18+
import java.util.Iterator;
19+
20+
21+
public final class Stats implements Serializable {
22+
23+
private final long count;
24+
private final double mean;
25+
private final double sumOfSquaresOfDeltas;
26+
private final double min;
27+
private final double max;
28+
29+
/**
30+
* Internal constructor. Users should use {@link #ofIterable} or {@link StatsAccumulator#snapshot}.
31+
*
32+
* <p>To ensure that the created instance obeys its contract, the parameters should satisfy the
33+
* following constraints. This is the callers responsibility and is not enforced here.
34+
*
35+
* <ul>
36+
* <li>If {@code count} is 0, {@code mean} may have any finite value (its only usage will be to
37+
* get multiplied by 0 to calculate the sum), and the other parameters may have any values
38+
* (they will not be used).
39+
* <li>If {@code count} is 1, {@code sumOfSquaresOfDeltas} must be exactly 0.0 or {@link
40+
* Double#NaN}.
41+
* </ul>
42+
*/
43+
Stats(long count, double mean, double sumOfSquaresOfDeltas, double min, double max) {
44+
this.count = count;
45+
this.mean = mean;
46+
this.sumOfSquaresOfDeltas = sumOfSquaresOfDeltas;
47+
this.min = min;
48+
this.max = max;
49+
}
50+
51+
/**
52+
* Returns statistics over a dataset containing the given values.
53+
*
54+
* @param values a series of values, which will be converted to {@code double} values (this may
55+
* cause loss of precision)
56+
*/
57+
public static Stats ofIterable(Iterable<? extends Number> values) {
58+
StatsAccumulator accumulator = new StatsAccumulator();
59+
accumulator.addAll(values);
60+
return accumulator.snapshot();
61+
}
62+
63+
/**
64+
* Returns statistics over a dataset containing the given values.
65+
*
66+
* @param values a series of values, which will be converted to {@code double} values (this may
67+
* cause loss of precision)
68+
*/
69+
public static Stats ofIterator(Iterator<? extends Number> values) {
70+
StatsAccumulator accumulator = new StatsAccumulator();
71+
accumulator.addAll(values);
72+
return accumulator.snapshot();
73+
}
74+
75+
/**
76+
* Returns statistics over a dataset containing the given values.
77+
*
78+
* @param values a series of values
79+
*/
80+
public static Stats ofDoubles(double... values) {
81+
StatsAccumulator acummulator = new StatsAccumulator();
82+
acummulator.addAll(values);
83+
return acummulator.snapshot();
84+
}
85+
86+
/**
87+
* Returns statistics over a dataset containing the given values.
88+
*
89+
* @param values a series of values
90+
*/
91+
public static Stats ofInts(int... values) {
92+
StatsAccumulator acummulator = new StatsAccumulator();
93+
acummulator.addAll(values);
94+
return acummulator.snapshot();
95+
}
96+
97+
/**
98+
* Returns statistics over a dataset containing the given values.
99+
*
100+
* @param values a series of values, which will be converted to {@code double} values (this may
101+
* cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
102+
*/
103+
public static Stats ofLongs(long... values) {
104+
StatsAccumulator acummulator = new StatsAccumulator();
105+
acummulator.addAll(values);
106+
return acummulator.snapshot();
107+
}
108+
109+
/** Returns the number of values. */
110+
public long count() {
111+
return count;
112+
}
113+
114+
115+
private static final long serialVersionUID = 0;
116+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright (C) 2012 The Guava Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License
10+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11+
* or implied. See the License for the specific language governing permissions and limitations under
12+
* the License.
13+
*/
14+
15+
package guava.examples.math;
16+
17+
import java.util.Iterator;
18+
19+
import static java.lang.Double.*;
20+
21+
public final class StatsAccumulator {
22+
23+
// These fields must satisfy the requirements of Stats' constructor as well as those of the stat
24+
// methods of this class.
25+
private long count = 0;
26+
private double mean = 0.0; // any finite value will do, we only use it to multiply by zero for sum
27+
private double sumOfSquaresOfDeltas = 0.0;
28+
private double min = NaN; // any value will do
29+
private double max = NaN; // any value will do
30+
31+
/** Adds the given value to the dataset. */
32+
public void add(double value) {
33+
if (count == 0) {
34+
count = 1;
35+
mean = value;
36+
min = value;
37+
max = value;
38+
if (!isFinite(value)) {
39+
sumOfSquaresOfDeltas = NaN;
40+
}
41+
} else {
42+
count++;
43+
if (isFinite(value) && isFinite(mean)) {
44+
// Art of Computer Programming vol. 2, Knuth, 4.2.2, (15) and (16)
45+
double delta = value - mean;
46+
mean += delta / count;
47+
sumOfSquaresOfDeltas += delta * (value - mean);
48+
} else {
49+
mean = calculateNewMeanNonFinite(mean, value);
50+
sumOfSquaresOfDeltas = NaN;
51+
}
52+
min = Math.min(min, value);
53+
max = Math.max(max, value);
54+
}
55+
}
56+
57+
/**
58+
* Adds the given values to the dataset.
59+
*
60+
* @param values a series of values, which will be converted to {@code double} values (this may
61+
* cause loss of precision)
62+
*/
63+
public void addAll(Iterable<? extends Number> values) {
64+
for (Number value : values) {
65+
add(value.doubleValue());
66+
}
67+
}
68+
69+
/**
70+
* Adds the given values to the dataset.
71+
*
72+
* @param values a series of values, which will be converted to {@code double} values (this may
73+
* cause loss of precision)
74+
*/
75+
public void addAll(Iterator<? extends Number> values) {
76+
while (values.hasNext()) {
77+
add(values.next().doubleValue());
78+
}
79+
}
80+
81+
/**
82+
* Adds the given values to the dataset.
83+
*
84+
* @param values a series of values
85+
*/
86+
public void addAll(double... values) {
87+
for (double value : values) {
88+
add(value);
89+
}
90+
}
91+
92+
/**
93+
* Adds the given values to the dataset.
94+
*
95+
* @param values a series of values
96+
*/
97+
public void addAll(int... values) {
98+
for (int value : values) {
99+
add(value);
100+
}
101+
}
102+
103+
/**
104+
* Adds the given values to the dataset.
105+
*
106+
* @param values a series of values, which will be converted to {@code double} values (this may
107+
* cause loss of precision for longs of magnitude over 2^53 (slightly over 9e15))
108+
*/
109+
public void addAll(long... values) {
110+
for (long value : values) {
111+
add(value);
112+
}
113+
}
114+
115+
/** Returns an immutable snapshot of the current statistics. */
116+
public Stats snapshot() {
117+
return new Stats(count, mean, sumOfSquaresOfDeltas, min, max);
118+
}
119+
120+
/** Returns the number of values. */
121+
public long count() {
122+
return count;
123+
}
124+
125+
/**
126+
* Calculates the new value for the accumulated mean when a value is added, in the case where at
127+
* least one of the previous mean and the value is non-finite.
128+
*/
129+
static double calculateNewMeanNonFinite(double previousMean, double value) {
130+
/*
131+
* Desired behaviour is to match the results of applying the naive mean formula. In particular,
132+
* the update formula can subtract infinities in cases where the naive formula would add them.
133+
*
134+
* Consequently:
135+
* 1. If the previous mean is finite and the new value is non-finite then the new mean is that
136+
* value (whether it is NaN or infinity).
137+
* 2. If the new value is finite and the previous mean is non-finite then the mean is unchanged
138+
* (whether it is NaN or infinity).
139+
* 3. If both the previous mean and the new value are non-finite and...
140+
* 3a. ...either or both is NaN (so mean != value) then the new mean is NaN.
141+
* 3b. ...they are both the same infinities (so mean == value) then the mean is unchanged.
142+
* 3c. ...they are different infinities (so mean != value) then the new mean is NaN.
143+
*/
144+
if (isFinite(previousMean)) {
145+
// This is case 1.
146+
return value;
147+
} else if (isFinite(value) || previousMean == value) {
148+
// This is case 2. or 3b.
149+
return previousMean;
150+
} else {
151+
// This is case 3a. or 3c.
152+
return NaN;
153+
}
154+
}
155+
156+
public static boolean isFinite(double value) {
157+
return NEGATIVE_INFINITY < value && value < POSITIVE_INFINITY;
158+
}
159+
}

utbot-summary-tests/build.gradle

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apply from: "${parent.projectDir}/gradle/include/jvm-project.gradle"
2+
apply plugin: "java"
3+
4+
evaluationDependsOn(':utbot-framework')
5+
compileTestJava.dependsOn tasks.getByPath(':utbot-framework:testClasses')
6+
7+
dependencies {
8+
implementation(project(":utbot-framework"))
9+
implementation(project(':utbot-instrumentation'))
10+
testImplementation project(':utbot-sample')
11+
testImplementation group: 'junit', name: 'junit', version: junit4_version
12+
testCompile project(':utbot-framework').sourceSets.test.output
13+
}
14+
15+
test {
16+
useJUnitPlatform()
17+
}

0 commit comments

Comments
 (0)