Skip to content

Commit b265e28

Browse files
yjshenJoshRosen
authored andcommitted
[SPARK-9526] [SQL] Utilize randomized tests to reveal potential bugs in sql expressions
JIRA: https://issues.apache.org/jira/browse/SPARK-9526 This PR is a follow up of #7830, aiming at utilizing randomized tests to reveal more potential bugs in sql expression. Author: Yijie Shen <henry.yijieshen@gmail.com> Closes #7855 from yjshen/property_check.
1 parent f10660f commit b265e28

File tree

10 files changed

+410
-6
lines changed

10 files changed

+410
-6
lines changed

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ArithmeticExpressionSuite.scala

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
5252
checkEvaluation(Add(positiveShortLit, negativeShortLit), -1.toShort)
5353
checkEvaluation(Add(positiveIntLit, negativeIntLit), -1)
5454
checkEvaluation(Add(positiveLongLit, negativeLongLit), -1L)
55+
56+
DataTypeTestUtils.numericAndInterval.foreach { tpe =>
57+
checkConsistencyBetweenInterpretedAndCodegen(Add, tpe, tpe)
58+
}
5559
}
5660

5761
test("- (UnaryMinus)") {
@@ -71,6 +75,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
7175
checkEvaluation(UnaryMinus(negativeIntLit), - negativeInt)
7276
checkEvaluation(UnaryMinus(positiveLongLit), - positiveLong)
7377
checkEvaluation(UnaryMinus(negativeLongLit), - negativeLong)
78+
79+
DataTypeTestUtils.numericAndInterval.foreach { tpe =>
80+
checkConsistencyBetweenInterpretedAndCodegen(UnaryMinus, tpe)
81+
}
7482
}
7583

7684
test("- (Minus)") {
@@ -85,6 +93,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
8593
(positiveShort - negativeShort).toShort)
8694
checkEvaluation(Subtract(positiveIntLit, negativeIntLit), positiveInt - negativeInt)
8795
checkEvaluation(Subtract(positiveLongLit, negativeLongLit), positiveLong - negativeLong)
96+
97+
DataTypeTestUtils.numericAndInterval.foreach { tpe =>
98+
checkConsistencyBetweenInterpretedAndCodegen(Subtract, tpe, tpe)
99+
}
88100
}
89101

90102
test("* (Multiply)") {
@@ -99,6 +111,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
99111
(positiveShort * negativeShort).toShort)
100112
checkEvaluation(Multiply(positiveIntLit, negativeIntLit), positiveInt * negativeInt)
101113
checkEvaluation(Multiply(positiveLongLit, negativeLongLit), positiveLong * negativeLong)
114+
115+
DataTypeTestUtils.numericTypeWithoutDecimal.foreach { tpe =>
116+
checkConsistencyBetweenInterpretedAndCodegen(Multiply, tpe, tpe)
117+
}
102118
}
103119

104120
test("/ (Divide) basic") {
@@ -111,6 +127,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
111127
checkEvaluation(Divide(left, Literal.create(null, right.dataType)), null)
112128
checkEvaluation(Divide(left, Literal(convert(0))), null) // divide by zero
113129
}
130+
131+
DataTypeTestUtils.numericTypeWithoutDecimal.foreach { tpe =>
132+
checkConsistencyBetweenInterpretedAndCodegen(Divide, tpe, tpe)
133+
}
114134
}
115135

116136
test("/ (Divide) for integral type") {
@@ -144,6 +164,12 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
144164
checkEvaluation(Remainder(negativeIntLit, negativeIntLit), 0)
145165
checkEvaluation(Remainder(positiveLongLit, positiveLongLit), 0L)
146166
checkEvaluation(Remainder(negativeLongLit, negativeLongLit), 0L)
167+
168+
// TODO: the following lines would fail the test due to inconsistency result of interpret
169+
// and codegen for remainder between giant values, seems like a numeric stability issue
170+
// DataTypeTestUtils.numericTypeWithoutDecimal.foreach { tpe =>
171+
// checkConsistencyBetweenInterpretedAndCodegen(Remainder, tpe, tpe)
172+
// }
147173
}
148174

149175
test("Abs") {
@@ -161,6 +187,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
161187
checkEvaluation(Abs(negativeIntLit), - negativeInt)
162188
checkEvaluation(Abs(positiveLongLit), positiveLong)
163189
checkEvaluation(Abs(negativeLongLit), - negativeLong)
190+
191+
DataTypeTestUtils.numericTypeWithoutDecimal.foreach { tpe =>
192+
checkConsistencyBetweenInterpretedAndCodegen(Abs, tpe)
193+
}
164194
}
165195

166196
test("MaxOf basic") {
@@ -175,6 +205,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
175205
checkEvaluation(MaxOf(positiveShortLit, negativeShortLit), (positiveShort).toShort)
176206
checkEvaluation(MaxOf(positiveIntLit, negativeIntLit), positiveInt)
177207
checkEvaluation(MaxOf(positiveLongLit, negativeLongLit), positiveLong)
208+
209+
DataTypeTestUtils.ordered.foreach { tpe =>
210+
checkConsistencyBetweenInterpretedAndCodegen(MaxOf, tpe, tpe)
211+
}
178212
}
179213

180214
test("MaxOf for atomic type") {
@@ -196,6 +230,10 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
196230
checkEvaluation(MinOf(positiveShortLit, negativeShortLit), (negativeShort).toShort)
197231
checkEvaluation(MinOf(positiveIntLit, negativeIntLit), negativeInt)
198232
checkEvaluation(MinOf(positiveLongLit, negativeLongLit), negativeLong)
233+
234+
DataTypeTestUtils.ordered.foreach { tpe =>
235+
checkConsistencyBetweenInterpretedAndCodegen(MinOf, tpe, tpe)
236+
}
199237
}
200238

201239
test("MinOf for atomic type") {
@@ -222,4 +260,8 @@ class ArithmeticExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
222260
checkEvaluation(Pmod(positiveInt, negativeInt), positiveInt)
223261
checkEvaluation(Pmod(positiveLong, negativeLong), positiveLong)
224262
}
263+
264+
DataTypeTestUtils.numericTypeWithoutDecimal.foreach { tpe =>
265+
checkConsistencyBetweenInterpretedAndCodegen(MinOf, tpe, tpe)
266+
}
225267
}

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/BitwiseFunctionsSuite.scala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class BitwiseFunctionsSuite extends SparkFunSuite with ExpressionEvalHelper {
4545
checkEvaluation(BitwiseNot(negativeIntLit), ~negativeInt)
4646
checkEvaluation(BitwiseNot(positiveLongLit), ~positiveLong)
4747
checkEvaluation(BitwiseNot(negativeLongLit), ~negativeLong)
48+
49+
DataTypeTestUtils.integralType.foreach { dt =>
50+
checkConsistencyBetweenInterpretedAndCodegen(BitwiseNot, dt)
51+
}
4852
}
4953

5054
test("BitwiseAnd") {
@@ -68,6 +72,10 @@ class BitwiseFunctionsSuite extends SparkFunSuite with ExpressionEvalHelper {
6872
(positiveShort & negativeShort).toShort)
6973
checkEvaluation(BitwiseAnd(positiveIntLit, negativeIntLit), positiveInt & negativeInt)
7074
checkEvaluation(BitwiseAnd(positiveLongLit, negativeLongLit), positiveLong & negativeLong)
75+
76+
DataTypeTestUtils.integralType.foreach { dt =>
77+
checkConsistencyBetweenInterpretedAndCodegen(BitwiseAnd, dt, dt)
78+
}
7179
}
7280

7381
test("BitwiseOr") {
@@ -91,6 +99,10 @@ class BitwiseFunctionsSuite extends SparkFunSuite with ExpressionEvalHelper {
9199
(positiveShort | negativeShort).toShort)
92100
checkEvaluation(BitwiseOr(positiveIntLit, negativeIntLit), positiveInt | negativeInt)
93101
checkEvaluation(BitwiseOr(positiveLongLit, negativeLongLit), positiveLong | negativeLong)
102+
103+
DataTypeTestUtils.integralType.foreach { dt =>
104+
checkConsistencyBetweenInterpretedAndCodegen(BitwiseOr, dt, dt)
105+
}
94106
}
95107

96108
test("BitwiseXor") {
@@ -110,10 +122,13 @@ class BitwiseFunctionsSuite extends SparkFunSuite with ExpressionEvalHelper {
110122
checkEvaluation(BitwiseXor(nullLit, Literal(1)), null)
111123
checkEvaluation(BitwiseXor(Literal(1), nullLit), null)
112124
checkEvaluation(BitwiseXor(nullLit, nullLit), null)
113-
114125
checkEvaluation(BitwiseXor(positiveShortLit, negativeShortLit),
115126
(positiveShort ^ negativeShort).toShort)
116127
checkEvaluation(BitwiseXor(positiveIntLit, negativeIntLit), positiveInt ^ negativeInt)
117128
checkEvaluation(BitwiseXor(positiveLongLit, negativeLongLit), positiveLong ^ negativeLong)
129+
130+
DataTypeTestUtils.integralType.foreach { dt =>
131+
checkConsistencyBetweenInterpretedAndCodegen(BitwiseXor, dt, dt)
132+
}
118133
}
119134
}

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ConditionalExpressionSuite.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ class ConditionalExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
6666
testIf(_.toLong, TimestampType)
6767

6868
testIf(_.toString, StringType)
69+
70+
DataTypeTestUtils.propertyCheckSupported.foreach { dt =>
71+
checkConsistencyBetweenInterpretedAndCodegen(If, BooleanType, dt, dt)
72+
}
6973
}
7074

7175
test("case when") {
@@ -176,6 +180,10 @@ class ConditionalExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
176180
Literal(Timestamp.valueOf("2015-07-01 08:00:00")),
177181
Literal(Timestamp.valueOf("2015-07-01 10:00:00")))),
178182
Timestamp.valueOf("2015-07-01 08:00:00"), InternalRow.empty)
183+
184+
DataTypeTestUtils.ordered.foreach { dt =>
185+
checkConsistencyBetweenInterpretedAndCodegen(Least, dt, 2)
186+
}
179187
}
180188

181189
test("function greatest") {
@@ -218,6 +226,9 @@ class ConditionalExpressionSuite extends SparkFunSuite with ExpressionEvalHelper
218226
Literal(Timestamp.valueOf("2015-07-01 08:00:00")),
219227
Literal(Timestamp.valueOf("2015-07-01 10:00:00")))),
220228
Timestamp.valueOf("2015-07-01 10:00:00"), InternalRow.empty)
221-
}
222229

230+
DataTypeTestUtils.ordered.foreach { dt =>
231+
checkConsistencyBetweenInterpretedAndCodegen(Greatest, dt, 2)
232+
}
233+
}
223234
}

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
6060
}
6161
}
6262
checkEvaluation(DayOfYear(Literal.create(null, DateType)), null)
63+
checkConsistencyBetweenInterpretedAndCodegen(DayOfYear, DateType)
6364
}
6465

6566
test("Year") {
@@ -79,6 +80,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
7980
}
8081
}
8182
}
83+
checkConsistencyBetweenInterpretedAndCodegen(Year, DateType)
8284
}
8385

8486
test("Quarter") {
@@ -98,6 +100,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
98100
}
99101
}
100102
}
103+
checkConsistencyBetweenInterpretedAndCodegen(Quarter, DateType)
101104
}
102105

103106
test("Month") {
@@ -117,6 +120,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
117120
}
118121
}
119122
}
123+
checkConsistencyBetweenInterpretedAndCodegen(Month, DateType)
120124
}
121125

122126
test("Day / DayOfMonth") {
@@ -135,6 +139,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
135139
c.get(Calendar.DAY_OF_MONTH))
136140
}
137141
}
142+
checkConsistencyBetweenInterpretedAndCodegen(DayOfMonth, DateType)
138143
}
139144

140145
test("Seconds") {
@@ -149,6 +154,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
149154
checkEvaluation(Second(Literal(new Timestamp(c.getTimeInMillis))),
150155
c.get(Calendar.SECOND))
151156
}
157+
checkConsistencyBetweenInterpretedAndCodegen(Second, TimestampType)
152158
}
153159

154160
test("WeekOfYear") {
@@ -157,6 +163,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
157163
checkEvaluation(WeekOfYear(Cast(Literal(sdfDate.format(d)), DateType)), 15)
158164
checkEvaluation(WeekOfYear(Cast(Literal(ts), DateType)), 45)
159165
checkEvaluation(WeekOfYear(Cast(Literal("2011-05-06"), DateType)), 18)
166+
checkConsistencyBetweenInterpretedAndCodegen(WeekOfYear, DateType)
160167
}
161168

162169
test("DateFormat") {
@@ -184,6 +191,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
184191
}
185192
}
186193
}
194+
checkConsistencyBetweenInterpretedAndCodegen(Hour, TimestampType)
187195
}
188196

189197
test("Minute") {
@@ -200,6 +208,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
200208
c.get(Calendar.MINUTE))
201209
}
202210
}
211+
checkConsistencyBetweenInterpretedAndCodegen(Minute, TimestampType)
203212
}
204213

205214
test("date_add") {
@@ -218,6 +227,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
218227
DateAdd(Literal(Date.valueOf("2016-02-28")), positiveIntLit), 49627)
219228
checkEvaluation(
220229
DateAdd(Literal(Date.valueOf("2016-02-28")), negativeIntLit), -15910)
230+
checkConsistencyBetweenInterpretedAndCodegen(DateAdd, DateType, IntegerType)
221231
}
222232

223233
test("date_sub") {
@@ -236,6 +246,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
236246
DateSub(Literal(Date.valueOf("2016-02-28")), positiveIntLit), -15909)
237247
checkEvaluation(
238248
DateSub(Literal(Date.valueOf("2016-02-28")), negativeIntLit), 49628)
249+
checkConsistencyBetweenInterpretedAndCodegen(DateSub, DateType, IntegerType)
239250
}
240251

241252
test("time_add") {
@@ -254,6 +265,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
254265
checkEvaluation(
255266
TimeAdd(Literal.create(null, TimestampType), Literal.create(null, CalendarIntervalType)),
256267
null)
268+
checkConsistencyBetweenInterpretedAndCodegen(TimeAdd, TimestampType, CalendarIntervalType)
257269
}
258270

259271
test("time_sub") {
@@ -277,6 +289,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
277289
checkEvaluation(
278290
TimeSub(Literal.create(null, TimestampType), Literal.create(null, CalendarIntervalType)),
279291
null)
292+
checkConsistencyBetweenInterpretedAndCodegen(TimeSub, TimestampType, CalendarIntervalType)
280293
}
281294

282295
test("add_months") {
@@ -296,6 +309,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
296309
AddMonths(Literal(Date.valueOf("2016-02-28")), positiveIntLit), 1014213)
297310
checkEvaluation(
298311
AddMonths(Literal(Date.valueOf("2016-02-28")), negativeIntLit), -980528)
312+
checkConsistencyBetweenInterpretedAndCodegen(AddMonths, DateType, IntegerType)
299313
}
300314

301315
test("months_between") {
@@ -320,6 +334,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
320334
checkEvaluation(MonthsBetween(t, tnull), null)
321335
checkEvaluation(MonthsBetween(tnull, t), null)
322336
checkEvaluation(MonthsBetween(tnull, tnull), null)
337+
checkConsistencyBetweenInterpretedAndCodegen(MonthsBetween, TimestampType, TimestampType)
323338
}
324339

325340
test("last_day") {
@@ -337,6 +352,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
337352
checkEvaluation(LastDay(Literal(Date.valueOf("2016-01-06"))), Date.valueOf("2016-01-31"))
338353
checkEvaluation(LastDay(Literal(Date.valueOf("2016-02-07"))), Date.valueOf("2016-02-29"))
339354
checkEvaluation(LastDay(Literal.create(null, DateType)), null)
355+
checkConsistencyBetweenInterpretedAndCodegen(LastDay, DateType)
340356
}
341357

342358
test("next_day") {
@@ -370,6 +386,7 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
370386
ToDate(Literal(Date.valueOf("2015-07-22"))),
371387
DateTimeUtils.fromJavaDate(Date.valueOf("2015-07-22")))
372388
checkEvaluation(ToDate(Literal.create(null, DateType)), null)
389+
checkConsistencyBetweenInterpretedAndCodegen(ToDate, DateType)
373390
}
374391

375392
test("function trunc") {

0 commit comments

Comments
 (0)