test: cover reverseFlipsTheCharactersOfAString
This commit is contained in:
1 parent
5eedad6404
commit
795ba03620
1 file changed
+173
@@ -289,4 +289,177 @@ class EvaluatorTest {
|
|||||||
assertFailsWith<KestrelException> { evalConstant(CallExpression("MOD", listOf(intLit(1), intLit(0)))) }
|
assertFailsWith<KestrelException> { evalConstant(CallExpression("MOD", listOf(intLit(1), intLit(0)))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun reverseFlipsTheCharactersOfAString() {
|
||||||
|
assertEquals(Value.TextValue("cba"), evalConstant(CallExpression("REVERSE", listOf(textLit("abc")))))
|
||||||
|
assertEquals(Value.TextValue(""), evalConstant(CallExpression("REVERSE", listOf(textLit("")))))
|
||||||
|
assertFailsWith<KestrelException> { evalConstant(CallExpression("REVERSE", listOf(intLit(1)))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun leftAndRightTakeCharactersFromEachEndAndClampToTheStringsLength() {
|
||||||
|
assertEquals(Value.TextValue("hel"), evalConstant(CallExpression("LEFT", listOf(textLit("hello"), intLit(3)))))
|
||||||
|
assertEquals(Value.TextValue("llo"), evalConstant(CallExpression("RIGHT", listOf(textLit("hello"), intLit(3)))))
|
||||||
|
assertEquals(Value.TextValue("hello"), evalConstant(CallExpression("LEFT", listOf(textLit("hello"), intLit(100)))))
|
||||||
|
assertEquals(Value.TextValue("hello"), evalConstant(CallExpression("RIGHT", listOf(textLit("hello"), intLit(100)))))
|
||||||
|
assertEquals(Value.TextValue(""), evalConstant(CallExpression("LEFT", listOf(textLit("hello"), intLit(0)))))
|
||||||
|
assertEquals(Value.TextValue(""), evalConstant(CallExpression("RIGHT", listOf(textLit("hello"), intLit(-1)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun signReturnsMinusOneZeroOrOneAcrossEveryNumericType() {
|
||||||
|
assertEquals(Value.IntegerValue(1), evalConstant(CallExpression("SIGN", listOf(intLit(5)))))
|
||||||
|
assertEquals(Value.IntegerValue(-1), evalConstant(CallExpression("SIGN", listOf(intLit(-5)))))
|
||||||
|
assertEquals(Value.IntegerValue(0), evalConstant(CallExpression("SIGN", listOf(intLit(0)))))
|
||||||
|
assertEquals(Value.IntegerValue(1), evalConstant(CallExpression("SIGN", listOf(realLit(0.1)))))
|
||||||
|
assertEquals(Value.IntegerValue(-1), evalConstant(CallExpression("SIGN", listOf(realLit(-0.1)))))
|
||||||
|
val negativeDecimal = LiteralExpression(Value.DecimalValue(BigDecimal("-3.50")))
|
||||||
|
assertEquals(Value.IntegerValue(-1), evalConstant(CallExpression("SIGN", listOf(negativeDecimal))))
|
||||||
|
assertFailsWith<KestrelException> { evalConstant(CallExpression("SIGN", listOf(textLit("x")))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun truncCutsDigitsTowardZeroWithoutRoundingUnlikeRound() {
|
||||||
|
assertEquals(Value.IntegerValue(4), evalConstant(CallExpression("TRUNC", listOf(intLit(4)))))
|
||||||
|
assertEquals(Value.RealValue(1.9), evalConstant(CallExpression("TRUNC", listOf(realLit(1.99), intLit(1)))))
|
||||||
|
assertEquals(Value.RealValue(-1.9), evalConstant(CallExpression("TRUNC", listOf(realLit(-1.99), intLit(1)))))
|
||||||
|
val decimal = LiteralExpression(Value.DecimalValue(BigDecimal("1.999")))
|
||||||
|
assertEquals(
|
||||||
|
Value.DecimalValue(BigDecimal("1.99")),
|
||||||
|
evalConstant(CallExpression("TRUNC", listOf(decimal, intLit(2))))
|
||||||
|
)
|
||||||
|
// TRUNC never rounds up, exactly the case where it must differ from ROUND's HALF_UP default.
|
||||||
|
assertEquals(Value.RealValue(1.0), evalConstant(CallExpression("TRUNC", listOf(realLit(1.9)))))
|
||||||
|
assertEquals(Value.RealValue(2.0), evalConstant(CallExpression("ROUND", listOf(realLit(1.9)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun greatestAndLeastPickTheOrderingExtremeAcrossMixedNumericTypes() {
|
||||||
|
assertEquals(
|
||||||
|
Value.IntegerValue(7),
|
||||||
|
evalConstant(CallExpression("GREATEST", listOf(intLit(3), intLit(7), intLit(1))))
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Value.IntegerValue(1),
|
||||||
|
evalConstant(CallExpression("LEAST", listOf(intLit(3), intLit(7), intLit(1))))
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Value.RealValue(7.5),
|
||||||
|
evalConstant(CallExpression("GREATEST", listOf(intLit(3), realLit(7.5), intLit(1))))
|
||||||
|
)
|
||||||
|
assertEquals(Value.TextValue("banana"), evalConstant(CallExpression("GREATEST", listOf(textLit("apple"), textLit("banana")))))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun greatestAndLeastPropagateNullAndRequireAtLeastTwoArguments() {
|
||||||
|
assertEquals(Value.NullValue, evalConstant(CallExpression("GREATEST", listOf(intLit(1), nullLit))))
|
||||||
|
assertEquals(Value.NullValue, evalConstant(CallExpression("LEAST", listOf(nullLit, intLit(1)))))
|
||||||
|
assertFailsWith<KestrelException> { evalConstant(CallExpression("GREATEST", listOf(intLit(1)))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun functionRequiringTextRejectsWrongType() {
|
||||||
|
assertFailsWith<KestrelException> { evalConstant(CallExpression("UPPER", listOf(intLit(1)))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isNullDetectsNullness() {
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(IsNullExpression(nullLit, negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(IsNullExpression(intLit(1), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(IsNullExpression(intLit(1), negated = true)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(IsNullExpression(nullLit, negated = true)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun inMatchesAnyListMember() {
|
||||||
|
assertEquals(
|
||||||
|
Value.BooleanValue(true),
|
||||||
|
evalConstant(InExpression(intLit(2), listOf(intLit(1), intLit(2), intLit(3)), negated = false))
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Value.BooleanValue(false),
|
||||||
|
evalConstant(InExpression(intLit(9), listOf(intLit(1), intLit(2)), negated = false))
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
Value.BooleanValue(false),
|
||||||
|
evalConstant(InExpression(intLit(2), listOf(intLit(1), intLit(2)), negated = true))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun inWithNullOperandIsNull() {
|
||||||
|
assertEquals(Value.NullValue, evalConstant(InExpression(nullLit, listOf(intLit(1)), negated = false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun inWithUnmatchedNullInListIsNullNotFalse() {
|
||||||
|
assertEquals(
|
||||||
|
Value.NullValue,
|
||||||
|
evalConstant(InExpression(intLit(9), listOf(intLit(1), nullLit), negated = false))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun betweenIsInclusiveOnBothEnds() {
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(BetweenExpression(intLit(18), intLit(18), intLit(65), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(BetweenExpression(intLit(65), intLit(18), intLit(65), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(BetweenExpression(intLit(17), intLit(18), intLit(65), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(BetweenExpression(intLit(17), intLit(18), intLit(65), negated = true)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun likeSupportsPercentAndUnderscoreWildcards() {
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(LikeExpression(textLit("hello"), textLit("h%"), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(LikeExpression(textLit("hello"), textLit("h_llo"), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(LikeExpression(textLit("hello"), textLit("world"), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(LikeExpression(textLit("hello"), textLit("h%"), negated = true)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun likeEscapesRegexMetacharactersInPattern() {
|
||||||
|
assertEquals(Value.BooleanValue(true), evalConstant(LikeExpression(textLit("a.b"), textLit("a.b"), negated = false)))
|
||||||
|
assertEquals(Value.BooleanValue(false), evalConstant(LikeExpression(textLit("axb"), textLit("a.b"), negated = false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun searchedCaseReturnsFirstMatchingBranch() {
|
||||||
|
val expression = CaseExpression(
|
||||||
|
operand = null,
|
||||||
|
branches = listOf(
|
||||||
|
CaseBranch(bin(BinaryOperator.Less, intLit(10), intLit(5)), textLit("small")),
|
||||||
|
CaseBranch(bin(BinaryOperator.GreaterEqual, intLit(10), intLit(5)), textLit("big"))
|
||||||
|
),
|
||||||
|
elseExpression = textLit("none")
|
||||||
|
)
|
||||||
|
assertEquals(Value.TextValue("big"), evalConstant(expression))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun simpleCaseComparesOperandAgainstBranches() {
|
||||||
|
val expression = CaseExpression(
|
||||||
|
operand = intLit(2),
|
||||||
|
branches = listOf(CaseBranch(intLit(1), textLit("one")), CaseBranch(intLit(2), textLit("two"))),
|
||||||
|
elseExpression = textLit("other")
|
||||||
|
)
|
||||||
|
assertEquals(Value.TextValue("two"), evalConstant(expression))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun caseFallsThroughToElseWhenNoBranchMatches() {
|
||||||
|
val expression = CaseExpression(
|
||||||
|
operand = null,
|
||||||
|
branches = listOf(CaseBranch(falseLit, textLit("nope"))),
|
||||||
|
elseExpression = textLit("fallback")
|
||||||
|
)
|
||||||
|
assertEquals(Value.TextValue("fallback"), evalConstant(expression))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun caseWithoutElseYieldsNullWhenNoBranchMatches() {
|
||||||
|
val expression = CaseExpression(operand = null, branches = listOf(CaseBranch(falseLit, textLit("nope"))), elseExpression = null)
|
||||||
|
assertEquals(Value.NullValue, evalConstant(expression))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cast(operand: Expression, type: ColumnType, precision: Int? = null, scale: Int? = null): Expression =
|
||||||
|
CastExpression(operand, type, precision, scale)
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user