Skip to content

Commit

Permalink
Add non-deterministic tests for ValueEnums (#69)
Browse files Browse the repository at this point in the history
* Add non-deterministic tests for ValueEnums
* Add invalid values check
  • Loading branch information
lloydmeta committed Aug 30, 2016
1 parent f081333 commit 5f4dfad
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -19,6 +19,7 @@ Enumeratum has the following niceties:
environments where reflection is a best effort (such as Android)
- No usage of `synchronized`, which may help with performance and deadlocks prevention
- All magic happens at compile-time so you know right away when things go awry
- Comprehensive automated testing to make sure everything is in tip-top shape

Compatible with Scala 2.11+ and 2.10 as well as ScalaJS.

Expand Down
@@ -0,0 +1,71 @@
package enumeratum.values

import enumeratum.Eval
import org.scalatest.{ FunSpec, Matchers }

import scala.reflect.ClassTag
import scala.util.Random

/**
* Created by Lloyd on 8/30/16.
*
* Copyright 2016
*/
class ValueEnumJVMSpec extends FunSpec with Matchers {

private def stringGenerator = Random.alphanumeric.grouped(10).toStream.map(_.mkString.replaceAll("[0-9]", "")).distinct

/*
Non-deterministically generates a bunch of different types of ValueEnums and tests the ability to resolve
proper members by value
*/
testValuesOf(Stream.continually(Random.nextInt()))
testValuesOf(Stream.continually(Random.nextLong()), valueSuffix = "L")
testValuesOf(Stream.continually(Random.nextInt()).collect { case i if i >= Short.MinValue && i <= Short.MaxValue => i.toShort })
testValuesOf(stringGenerator, "\"", "\"")

private def testValuesOf[A: ClassTag](valuesGenerator: => Stream[A], valuePrefix: String = "", valueSuffix: String = ""): Unit = {

val typeName = implicitly[ClassTag[A]].runtimeClass.getSimpleName.capitalize

describe(s"${typeName}Enum withValue") {

it("should return proper members for valid values but throw otherwise") {
(1 to 20).foreach { i =>
val enumName = s"Generated${typeName}Enum$i"
val names = stringGenerator.take(5)
val values = valuesGenerator.distinct.take(5)
val namesToValues = names.zip(values)
val memberDefs = namesToValues.map { case (n, v) => s"""case object $n extends $enumName($valuePrefix$v$valueSuffix)""" }.mkString("\n\n")
val objDef =
s"""
|import enumeratum.values._
|
|sealed abstract class $enumName(val value: $typeName) extends ${typeName}EnumEntry
|
|object $enumName extends ${typeName}Enum[$enumName] {
| val values = findValues
|
| $memberDefs
|}
|$enumName
""".stripMargin
val obj = Eval.apply[ValueEnum[A, _ <: ValueEnumEntry[A]]](objDef)
namesToValues.foreach {
case (n, v) =>
obj.withValue(v).toString shouldBe n
}
// filterNot is not lazy until 2.12
valuesGenerator.filter(a => !values.contains(a)).take(5).foreach { invalidValue =>
intercept[NoSuchElementException] {
obj.withValue(invalidValue)
}
}
}
}

}

}

}

0 comments on commit 5f4dfad

Please sign in to comment.