blob: 96918418170af83143e04204c4dd8eb5c20a0ad1 [file] [log] [blame]
/*
* Copyright 2003-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package gls.enums
import gls.CompilableTestSupport
/**
* Tests various properties of enums.
*
* @author Paul King
* @author Roshan Dawrani
*/
class EnumTest extends CompilableTestSupport {
void testValues() {
assert UsCoin.values().size() == 4
assert UsCoin.values().toList().sum{ it.value } == 41
}
void testNext() {
def coin = UsCoin.penny
def coins = [coin++, coin++, coin++, coin++, coin]
assert coins == [UsCoin.penny, UsCoin.nickel, UsCoin.dime, UsCoin.quarter, UsCoin.penny]
}
void testPrevious() {
def coin = UsCoin.quarter
def coins = [coin--, coin--, coin--, coin--, coin]
assert coins == [UsCoin.quarter, UsCoin.dime, UsCoin.nickel, UsCoin.penny, UsCoin.quarter]
}
void testRange() {
def coinRange1 = UsCoin.penny..UsCoin.dime
assert (UsCoin.nickel in coinRange1)
assert !(UsCoin.quarter in coinRange1)
}
void testMinValue() {
assert UsCoin.MIN_VALUE == UsCoin.penny
shouldFail(MissingPropertyException) {
EmptyEnum.MIN_VALUE
}
}
void testMaxValue() {
assert UsCoin.MAX_VALUE == UsCoin.quarter
shouldFail(MissingPropertyException) {
EmptyEnum.MAX_VALUE
}
}
void testComparators() {
assert UsCoin.nickel <=> UsCoin.penny == 1
assert UsCoin.nickel <=> UsCoin.nickel == 0
assert UsCoin.nickel <=> UsCoin.dime == -1
assert UsCoin.nickel <= UsCoin.nickel
assert UsCoin.nickel <= UsCoin.dime
assert UsCoin.nickel >= UsCoin.penny
assert UsCoin.nickel >= UsCoin.nickel
}
void testStepWithRange() {
def coinRange2 = UsCoin.nickel..UsCoin.quarter
def coins = coinRange2.toList()
assert coins == [UsCoin.nickel, UsCoin.dime, UsCoin.quarter]
coins = coinRange2.step(2)
assert coins == [UsCoin.nickel, UsCoin.quarter]
coins = coinRange2.step(3)
assert coins == [UsCoin.nickel]
coins = coinRange2.step(4)
assert coins == [UsCoin.nickel]
coins = coinRange2.step(-1)
assert coins == [UsCoin.quarter, UsCoin.dime, UsCoin.nickel]
coins = coinRange2.step(-2)
assert coins == [UsCoin.quarter, UsCoin.nickel]
coins = coinRange2.step(-3)
assert coins == [UsCoin.quarter]
coins = coinRange2.step(-4)
assert coins == [UsCoin.quarter]
}
void testStepWithReverseRange() {
def coinRange2 = UsCoin.quarter..UsCoin.nickel
def coins = coinRange2.toList()
assert coins == [UsCoin.quarter, UsCoin.dime, UsCoin.nickel]
coins = coinRange2.step(2)
assert coins == [UsCoin.quarter, UsCoin.nickel]
coins = coinRange2.step(3)
assert coins == [UsCoin.quarter]
coins = coinRange2.step(4)
assert coins == [UsCoin.quarter]
coins = coinRange2.step(-1)
assert coins == [UsCoin.nickel, UsCoin.dime, UsCoin.quarter]
coins = coinRange2.step(-2)
assert coins == [UsCoin.nickel, UsCoin.quarter]
coins = coinRange2.step(-3)
assert coins == [UsCoin.nickel]
coins = coinRange2.step(-4)
assert coins == [UsCoin.nickel]
}
void testEnumWithSingleListInConstructor() {
def sh = new GroovyShell();
def enumStr;
enumStr = """
enum ListEnum1 {
ONE([111, 222])
ListEnum1(Object listArg){
assert listArg == [111, 222]
assert listArg instanceof java.util.ArrayList
}
}
println ListEnum1.ONE
"""
sh.evaluate(enumStr);
enumStr = """
enum ListEnum2 {
TWO([234, [567,12]])
ListEnum2(Object listArg){
assert listArg == [234, [567, 12]]
assert listArg instanceof java.util.ArrayList
}
}
println ListEnum2.TWO
"""
sh.evaluate(enumStr);
}
void testSingleListDoesNoInfluenceMaps() {
// the fix for GROOVY-2933 caused map["taku"]
// to become map[(["take])] instead. -> GROOVY-3214
assertScript """
public enum FontFamily {
ARIAL
static public void obtainMyMap()
{
Map map = [:]
map["taku"] = "dio"
assert map.taku == "dio"
}
}
FontFamily.obtainMyMap()
"""
}
void testMutipleValuesDontGetWronglyWrappedInList() {
// the fix for GROOVY-3214 caused multiple values passed in an enum const
// to get wrapped in an extra ListExpression. -> GROOVY-3276
assertScript """
enum GROOVY3276 {
A(1,2), B(3,4)
GROOVY3276(int xx, int yy) {
x=xx
y=yy
}
public int x
public int y
}
assert GROOVY3276.A.x == 1
assert GROOVY3276.B.y == 4
"""
}
// the fix for GROOVY-3161
def void testStaticEnumFieldWithEnumValues() {
def allColors = GroovyColors3161.ALL_COLORS
assert allColors.size == 3
assert allColors[0] == GroovyColors3161.red
assert allColors[1] == GroovyColors3161.blue
assert allColors[2] == GroovyColors3161.green
}
// the fix for GROOVY-3283
def void testImportStaticMoreThanOneEnum() {
assertScript """
enum Foo3283 { A,B }
enum Bar3283 { X,Y }
import static Foo3283.*
import static Bar3283.*
a = A
x = X
"""
}
void testCallBehaviorOnEnumForGROOVY3284() {
// test the usage in a non-script class first
for (f in Foo3284) {
assert f() == "A"
}
assert Foo3284.A.call() == "A"
assert Foo3284.A() == "A"
def a = Foo3284.A
assert a() == "A"
// now test the usage in a script but this time type Closure not specified explicitly
assertScript """
enum Foo32842 {
B({ "B" })
Foo32842(c) {
call = c
}
def call
}
for (f in Foo32842) {
assert f() == "B"
}
assert Foo32842.B.call() == "B"
assert Foo32842.B() == "B"
b = Foo32842.B
assert b() == "B"
"""
}
void testClassResolutionForInnerEnumsWithPackageNameGROOVY3483() {
assertScript """
package familie
class Mother3483 {
Mother3483.Child child
enum Child{
Franz,
Ferdi,
Nand
}
}
def mother = new Mother3483(child: Mother3483.Child.Franz)
assert mother.child as String == 'Franz'
"""
}
void testInnerEnumUsedInDefiningClassWithUnqualifiedEnumNameUsed() {
//GROOVY-3110
assertScript """
class Class3110 {
enum Enum3110{FOO, BAR}
Enum3110 var
def setEnumVar() {
var = Enum3110.FOO
}
def getEnumVar() {
var
}
}
def obj = new Class3110()
obj.setEnumVar()
assert obj.getEnumVar() == Class3110.Enum3110.FOO
"""
}
void testStaticFieldInitValuesInAStaticBlock() {
// GROOVY-3693 - trigger enum class load to test it - asserts are present in the enum
GrooyColors3693.r
}
void testCustomMethodOnEnum() {
// GROOVY-2443
assertScript """
enum Day {
SUNDAY {
String activity() { 'Relax' }
}, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
String activity() { 'Work' }
}
assert "Work" == Day.MONDAY.activity()
assert "Relax" == Day.SUNDAY.activity()
"""
}
void testEnumConstantSubClassINITMethodOverrideINITOfEnumClass() {
try {
// cause loading of enum that causes its fields to be set and
// their instance initializer to be executed
println Color3985
}catch(ExceptionInInitializerError err) {
assert err.cause.message == 'Color3985 RED instance initializer called successfully'
}
}
void testEnumStaticInitWithAFieldUsingEnumValues() {
//GROOVY-3996
assertScript """
enum Color3996 {
R, G, B
public static Color3996[] ALL_COLORS = [R, G, B]
}
assert Color3996.ALL_COLORS.size() == 3
assert Color3996.ALL_COLORS[0] == Color3996.R
assert Color3996.ALL_COLORS[1] == Color3996.G
assert Color3996.ALL_COLORS[2] == Color3996.B
"""
}
void testEnumWithTopLevelNoBracketsMethodCall() {
// GROOVY-3986
assertScript """
enum Color3986 {
RED {
String toString() { sprintf '%s', 'foo' }
},GREEN,BLUE
}
assert Color3986.RED.toString() == 'foo'
"""
}
void testEnumConstantSeparators() {
// GROOVY-3047
shouldCompile """
enum Foo0 { X }
enum Foo1 {
Y
}
enum Foo2 {
Z,
}
enum Foo3 { X, Y, Z,
}
enum Foo4 {
X
,
}
enum Foo5 {
X
,
Y
}
enum Foo6 {
X
,
Y,
}
enum Foo7 {
X
,
Y
,
}
"""
}
void testEnumWithSingleValueAndClassField() {
// GROOVY-4268
shouldCompile """
private enum EnumWithSingleValueAndClassField {
VALUE
String toString() { "I'm a value" }
}
"""
}
void testConstructorChainingInEnum() {
// GROOVY-4444
assertScript """
enum Foo4444 {
ONE(1), TWO(1, 2)
int i
int j
Foo4444(int i) {
this(i, 0)
}
Foo4444(int i, int j) {
this.i = i
this.j = j
}
}
def foos = [Foo4444.ONE, Foo4444.TWO]
assert foos.size() == 2
assert foos[0].i == 1
assert foos[0].j == 0
assert foos[1].i == 1
assert foos[1].j == 2
"""
}
void testNamedArguments() {
// this test is a result of GROOVY-4219 and should be changed once
// GROOVY-4582 is implemented.
shouldNotCompile """
enum ImageSortField {
FILENAME(field: null, name: null),
TIME(field: null, name: null)
def field
def name
public String toString(){
name
}
}
"""
}
}
enum UsCoin {
penny(1), nickel(5), dime(10), quarter(25)
UsCoin(int value) { this.value = value }
private final int value
int getValue() { value }
}
enum EmptyEnum{}
enum GroovyColors3161 {
red, blue, green
static def ALL_COLORS = [red, blue, green]
}
enum GroovyColors3161B {
red, blue, green,
static def ALL_COLORS = [red, blue, green]
}
enum Foo3284 {
A({ "A" })
Foo3284(Closure c) {
call = c
}
final Closure call
}
enum GrooyColors3693 {
r, g, b
static List list = [1, 2]
static init() {
assert list == [1, 2]
}
static {
init()
}
}
enum Color3985 {
RED {
{
throw new RuntimeException('Color3985 RED instance initializer called successfully')
}
},GREEN,BLUE
}