Skip to content

Commit cd7b785

Browse files
authored
Render multidimensional arrays in comparisons and invocation matchers
1 parent de22b9d commit cd7b785

File tree

4 files changed

+143
-58
lines changed

4 files changed

+143
-58
lines changed

spock-core/src/main/java/org/spockframework/util/RenderUtil.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.spockframework.runtime.GroovyRuntimeUtil;
44

55
import java.util.*;
6+
import java.util.function.Function;
67

78
import groovy.lang.Range;
89
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
@@ -52,7 +53,10 @@ public static String toStringOrDump(@Nullable Object value) {
5253
Wrapper wrapper = (Wrapper) value;
5354
return String.format("%s as %s", toStringOrDump(wrapper.unwrap()), wrapper.getType().getSimpleName());
5455
}
55-
return dump(value);
56+
if (value.getClass().isArray()) {
57+
return dumpArrayString((Object[]) value, RenderUtil::toStringOrDump);
58+
}
59+
return DefaultGroovyMethods.dump(value);
5660
}
5761

5862
public static String inspectOrDump(@Nullable Object value) {
@@ -63,28 +67,22 @@ public static String inspectOrDump(@Nullable Object value) {
6367
Wrapper wrapper = (Wrapper) value;
6468
return String.format("%s as %s", inspectOrDump(wrapper.unwrap()), wrapper.getType().getSimpleName());
6569
}
66-
return dump(value);
67-
}
68-
69-
private static String dump(@Nullable Object value) {
7070
if (value.getClass().isArray()) {
71-
return dumpArrayString((Object[])value);
72-
} else {
73-
return DefaultGroovyMethods.dump(value);
71+
return dumpArrayString((Object[]) value, RenderUtil::inspectOrDump);
7472
}
73+
return DefaultGroovyMethods.dump(value);
7574
}
7675

77-
7876
/*
7977
* Adapted from org.codehaus.groovy.runtime.InvokerHelper.toArrayString(java.lang.Object[]) to use dump()
8078
*/
81-
private static String dumpArrayString(Object[] arguments) {
79+
private static String dumpArrayString(Object[] arguments, Function<Object, String> argDumper) {
8280
StringBuilder argBuf = new StringBuilder("[");
8381
for (int i = 0; i < arguments.length; i++) {
8482
if (i > 0) {
8583
argBuf.append(", ");
8684
}
87-
argBuf.append(DefaultGroovyMethods.dump(arguments[i]));
85+
argBuf.append(argDumper.apply(arguments[i]));
8886
}
8987
argBuf.append("]");
9088
return argBuf.toString();
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.spockframework.smoke.condition
2+
3+
import static org.spockframework.smoke.condition.ValueRendering.DefaultToString
4+
5+
class ArrayComparisonRendering extends ConditionRenderingSpec {
6+
7+
def "primitive array value"() {
8+
expect:
9+
isRendered """
10+
x == null
11+
| |
12+
| false
13+
[1, 2]
14+
""", {
15+
def x = [1, 2] as int[]
16+
assert x == null
17+
}
18+
}
19+
20+
def "object array value"() {
21+
expect:
22+
isRendered """
23+
x == null
24+
| |
25+
| false
26+
[one, two]
27+
""", {
28+
def x = ["one", "two"] as String[]
29+
assert x == null
30+
}
31+
}
32+
33+
def "arrays of variables with default to string is dump()ed"() {
34+
def a = new DefaultToString()
35+
def b = new DefaultToString()
36+
DefaultToString[] x = [a, b]
37+
expect:
38+
isRendered """
39+
x == null
40+
| |
41+
| false
42+
[${a.dump()}, ${b.dump()}]
43+
""", {
44+
assert x == null
45+
}
46+
}
47+
48+
def "primitive two-dimensional array value"() {
49+
expect:
50+
isRendered """
51+
x == y
52+
| | |
53+
| | [[1, 2], [1, 5]]
54+
| false
55+
[[1, 2], [2, 5]]
56+
""", {
57+
def x = [[1, 2], [2, 5]] as int[][]
58+
def y = [[1, 2], [1, 5]] as int[][]
59+
assert x == y
60+
}
61+
}
62+
63+
def "object two-dimensional array value"() {
64+
expect:
65+
isRendered """
66+
x == y
67+
| | |
68+
| | [[one, two], [one, five]]
69+
| false
70+
[[one, two], [two, five]]
71+
""", {
72+
def x = [["one", "two"], ["two", "five"]] as String[][]
73+
def y = [["one", "two"], ["one", "five"]] as String[][]
74+
assert x == y
75+
}
76+
}
77+
78+
def "multidimensional array value with higher cardinality"() {
79+
expect:
80+
isRendered """
81+
x == y
82+
| | |
83+
| | [[[1, 2], [1, 5]], [[1, 2], [1, 5]]]
84+
| false
85+
[[[1, 2], [2, 5]], [[1, 2], [2, 5]]]
86+
""", {
87+
def x = [[[1, 2], [2, 5]], [[1, 2], [2, 5]]] as int[][][]
88+
def y = [[[1, 2], [1, 5]], [[1, 2], [1, 5]]] as int[][][]
89+
assert x == y
90+
}
91+
}
92+
93+
}

spock-specs/src/test/groovy/org/spockframework/smoke/condition/ValueRendering.groovy

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,6 @@ null == x
9393
}
9494
}
9595

96-
def "primitive array value"() {
97-
expect:
98-
isRendered """
99-
x == null
100-
| |
101-
| false
102-
[1, 2]
103-
""", {
104-
def x = [1, 2] as int[]
105-
assert x == null
106-
}
107-
}
108-
109-
def "object array value"() {
110-
expect:
111-
isRendered """
112-
x == null
113-
| |
114-
| false
115-
[one, two]
116-
""", {
117-
def x = ["one", "two"] as String[]
118-
assert x == null
119-
}
120-
}
121-
12296
def "list value"() {
12397
expect:
12498
isRendered """
@@ -127,7 +101,7 @@ x == null
127101
| false
128102
[1, 2, 3]
129103
""", {
130-
def x = [1,2,3]
104+
def x = [1, 2, 3]
131105
assert x == null
132106
}
133107
}
@@ -277,21 +251,6 @@ ${x.dump()}
277251
}
278252
}
279253
280-
def "arrays of variables with default to string is dump()ed"() {
281-
def a = new DefaultToString()
282-
def b = new DefaultToString()
283-
DefaultToString[] x = [a, b]
284-
expect:
285-
isRendered """
286-
x == null
287-
| |
288-
| false
289-
[${a.dump()}, ${b.dump()}]
290-
""", {
291-
assert x == null
292-
}
293-
}
294-
295254
static class SingleLineToString {
296255
String toString() {
297256
"single line"
@@ -337,6 +296,7 @@ x == null
337296
338297
enum EnumWithToString {
339298
VALUE;
299+
340300
String toString() { "I'm a value" }
341301
}
342302
}

spock-specs/src/test/groovy/org/spockframework/smoke/mock/TooFewInvocations.groovy

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@
1616

1717
package org.spockframework.smoke.mock
1818

19+
import org.hamcrest.CoreMatchers
1920
import org.spockframework.EmbeddedSpecification
2021
import org.spockframework.mock.TooFewInvocationsError
2122

2223
import java.util.regex.Pattern
2324

24-
import org.hamcrest.CoreMatchers
25-
2625
class TooFewInvocations extends EmbeddedSpecification {
27-
static Pattern EMPTY_LINE = Pattern.compile(/^ ++$/,Pattern.MULTILINE)
26+
static Pattern EMPTY_LINE = Pattern.compile(/^ ++$/, Pattern.MULTILINE)
2827

2928
def "shows unmatched invocations, ordered by similarity"() {
3029
when:
@@ -559,6 +558,7 @@ One or more arguments(s) didn't match:
559558
""".trim())
560559
exceptionMessage == expected
561560
}
561+
562562
def "can describe code argument with verifyAll"() {
563563
when:
564564
runner.addClassImport(PersonWithFirstname)
@@ -1157,6 +1157,40 @@ then:
11571157
exceptionMessage =~ /(?m)^\Q1 * list.add(<org.spockframework.smoke.mock.TooFewInvocations\E.Person@\w+ name=Foo age=18>\)$/
11581158
}
11591159
1160+
def "correctly renders multidimensional arrays"() {
1161+
when:
1162+
runner.runFeatureBody("""
1163+
def list = Mock(List)
1164+
def arr = [[1, 2], [2, 5]] as int[][]
1165+
1166+
when:
1167+
list.add(arr)
1168+
1169+
then:
1170+
1 * list.add('bar')
1171+
""")
1172+
1173+
then:
1174+
TooFewInvocationsError e = thrown()
1175+
def exceptionMessage = normalize(e.message)
1176+
def expected = normalize("""
1177+
Too few invocations for:
1178+
1179+
1 * list.add('bar') (0 invocations)
1180+
1181+
Unmatched invocations (ordered by similarity):
1182+
1183+
1 * list.add([[1, 2], [2, 5]])
1184+
One or more arguments(s) didn't match:
1185+
0: argument == expected
1186+
| | |
1187+
| | bar
1188+
| false
1189+
[[1, 2], [2, 5]]
1190+
""".trim())
1191+
exceptionMessage == expected
1192+
}
1193+
11601194
String normalize(String str) {
11611195
EMPTY_LINE.matcher(str.normalize().trim()).replaceAll('')
11621196
}
@@ -1165,15 +1199,15 @@ then:
11651199
String name
11661200
int age
11671201
1168-
String wife(String firstName, String surname, int age, String address){
1202+
String wife(String firstName, String surname, int age, String address) {
11691203
return ''
11701204
}
11711205
11721206
String family(Map args) {
11731207
return ''
11741208
}
11751209
1176-
String named(Map args, String a, String b){
1210+
String named(Map args, String a, String b) {
11771211
return ''
11781212
}
11791213
}

0 commit comments

Comments
 (0)