Generating arbitrary (legal) Unicode character with scalacheck?

心不动则不痛 提交于 2019-12-10 17:09:38

问题


I'm trying to create a generator that produces (non-zero-length) legal unicode strings, with scalacheck 1.6.6 and specs 1.7 (scala 2.8.1).

I hoped I could just create generators like:

object Generators {
  def unicodeChar: Gen[Char] = 
    choose(Math.MIN_CHAR, Math.MAX_CHAR).map(_.toChar).filter(
      c => Character.isDefined(c))
  def unicodeStr: Gen[String] = for(cs <- listOf1(unicodeChar)) yield cs.mkString
}

...then use them from specs like:

import org.specs.Specification
import org.specs.matcher.ScalaCheckMatchers

object CoreSpec extends Specification with ScalaCheckMatchers {        
  "The core" should {    
    "pass trivially" in {
      Generators.unicodeStr must pass((s: String) => s == s)
    }
  }
}

But, it seems that using filter in unicodeChar causes a problem:

Specification "CoreSpec"
  The core should
  x pass trivially
    Gave up after only 64 passed tests. 500 tests were discarded.

If I remove the filter from unicodeChar, my test passes, but I run into other problems later, since my strings are not always well-defined unicode.

Thanks in advance for any suggestions on how to achieve this.


回答1:


Try filtering out the characters before creating the generator:

val unicodeChar: Gen[Char] = Gen.oneOf((Math.MIN_CHAR to Math.MAX_CHAR).filter(Character.isDefined(_)))

It will be more memory intensive, since the complete list of unicode characters will be allocated when the generator is created, but only one instance of that list will be used so it shouldn't be a big problem.




回答2:


I don't know how it was in 2010, but nowadays you can use Arbitrary:

  import org.scalacheck.Arbitrary
  import org.scalacheck.Gen

  val unicodeChar: Gen[Char] = Arbitrary.arbChar.arbitrary
  val unicodeString: Gen[String] = Arbitrary.arbString.arbitrary



回答3:


Ok, I figured it out. This is what works for me:

def unicodeChar = Gen((p: Gen.Params) => {
    var c = 0
    do {
      c = util.Random.nextInt(0xFFFF)
    } while (!Character.isDefined(c))
    Some(c.toChar)
  })

Pretty simple, actually. What I didn't get is that you can create an arbitrary generator of type T by passing a function Gen.Params => T to Gen.apply().




回答4:


Have you tried suchThat instead of filter?



来源:https://stackoverflow.com/questions/4379055/generating-arbitrary-legal-unicode-character-with-scalacheck

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!