Skip to content

Generating values which depend on each other fails #79

@alfert

Description

@alfert

I am looking for a way to generate values which depend on each other. In particular, I want to recreate the following simple example from ScalaCheck's User Guide (https://github.com/typelevel/scalacheck/blob/main/doc/UserGuide.md#generators), where two integer are generated, the first in the range of 10..20, the second has a lower bound which is twice as large as the first value:

// ScalaCheck Example
val myGen = for {
  n <- Gen.choose(10,20)
  m <- Gen.choose(2*n, 500)
} yield (n,m)

My impression was that the gen.FlatMap() should provide the required functionality (in Scala, <- is a monadic assignment, implemented by FlatMap), but I failed to find a way to succeed.

I defined a simple struct to generate two values which can be fed into the property:

type IntPair struct {
		Fst int
		Snd int
	}
properties.Property("ScalaCheck example for a pair", prop.ForAll(
		func(p IntPair) bool {
			a := p.Fst
			b := p.Snd
			return a*2 <= b
		},
		genIntPairScala(),
	))

The generator is a straight translation of the Scala code, first generating an integer and then generating a second via accessing the generated value of the first. Both generators are finally stored in the struct generator:

genIntPairScala := func() gopter.Gen {
		n := gen.IntRange(10, 20).WithLabel("n (fst)")
		m := n.FlatMap(func(v interface{}) gopter.Gen {
			k := v.(int)
			return gen.IntRange(2*k, 50)
		}, reflect.TypeOf(int(0))).WithLabel("m (snd)")

		var gen_map = map[string]gopter.Gen{"Fst": n, "Snd": m}
		return gen.Struct(
			reflect.TypeOf(IntPair{}),
			gen_map,
		)
	}

However, it does not work:

=== RUN   TestGopterGenerators
! ScalaCheck example for a pair: Falsified after 10 passed tests.
n (fst), m (snd): {Fst:17 Snd:32}
n (fst), m (snd)_ORIGINAL (1 shrinks): {Fst:19 Snd:32}
Elapsed time: 233.121µs
    properties.go:57: failed with initial seed: 1617636578517672000

Remark: I set the upper bound to 50 instead of 500. The property must still hold, but the generator has a smaller pool to pick suitable values: setting the upper bound to 500 often results in a passing property!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions