Skip to content

How to write your own (complex) generator? #22

@meling

Description

@meling

I've been playing around with gopter for a little while now, trying to understand how to write my own generator for my use case, which is not as straight forward as those in the repo. My use case is the following; I want to test a function (ReadQF) that should return a value and true when enough, i.e. a quorum of replies have been received and passed in to the ReadQF function. It should return false otherwise.

I've hacked together something that seems to work in the following:

https://github.com/relab/byzq/blob/master/authdataspec_property_test.go#L37
https://github.com/relab/byzq/blob/master/authdataspec_property_test.go#L63

However, I suspect it isn't quite in the spirit of property-based testing, and I'm struggling to break it up into multiple generators, since the input parameter n to the NewAuthDataQ constructor that creates a qspec object and computes the parameter q, which is used to decide the minimal/maximal length of the replies array. And furthermore, I need access to the qspec object in the end to decide if a quorum has been received.

I would really appreciate to get some feedback on my two tests linked above, especially, if you can provide some advice on how to decouple things.

(Below is an initial attempt at writing a generator, but I don't know how to get both the quorumSize and qspec parameters out of the generator for consumption in the condition function passed to prop.ForAll().)

func genQuorums(min, max int, hasQuorum bool) gopter.Gen {
	return func(genParams *gopter.GenParameters) *gopter.GenResult {
		rangeSize := uint64(max - min + 1)
		n := int(uint64(min) + (genParams.NextUint64() % rangeSize))
		qspec, err := NewAuthDataQ(n, priv, &priv.PublicKey)
		if err != nil {
			panic(err)
		}
		// initialize as non-quorum
		minQuorum, maxQuorum := math.MinInt32, qspec.q
		if hasQuorum {
			minQuorum, maxQuorum = qspec.q+1, qspec.n
		}
		rangeSize = uint64(maxQuorum - minQuorum + 1)
		quorumSize := int(uint64(minQuorum) + (genParams.NextUint64() % rangeSize))

		genResult := gopter.NewGenResult(qspec, gopter.NoShrinker)
		return genResult
	}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions