0 views

Skip to first unread message

Jun 5, 2008, 8:40:17 AM6/5/08

to Reductio

Hi,

I'm currently trying out Reductio with a very simple Generator java

class. I'm testing a method that gets two arguments that have certain

preconditions.

My first attempt at this fails pretty quickly due to the second

argument violating its precondition (must be > 0 and > first

argument):

Property p = property(arbitrary(Gen.choose(1, 1000)),

arbitrary(Gen.choose(1, 1000)), new F2<Integer, Integer, Property>() {

public Property f(final Integer size, final Integer range) {

return prop(new Generator().generate(size, range).size() == size);

}

});

I then tried to put the precondition into the Property:

Property p = property(arbitrary(Gen.choose(1, 1000)),

arbitrary(Gen.choose(1, 5000)), new F2<Integer, Integer, Property>() {

public Property f(final Integer size, final Integer range) {

return bool(range > size).implies(new Generator().generate(size,

range).size() == size);

}

});

The problem here is that the generate method is still called with

invalid arguments, but that isn't allowed to happen. I tried to use

Gen.sized to replace Gen.choose, but can't figure out how to create a

tuple based on that.

Any ideas how to express those preconditions with Reductio?

Thanks

Jörn

I'm currently trying out Reductio with a very simple Generator java

class. I'm testing a method that gets two arguments that have certain

preconditions.

My first attempt at this fails pretty quickly due to the second

argument violating its precondition (must be > 0 and > first

argument):

Property p = property(arbitrary(Gen.choose(1, 1000)),

arbitrary(Gen.choose(1, 1000)), new F2<Integer, Integer, Property>() {

public Property f(final Integer size, final Integer range) {

return prop(new Generator().generate(size, range).size() == size);

}

});

I then tried to put the precondition into the Property:

Property p = property(arbitrary(Gen.choose(1, 1000)),

arbitrary(Gen.choose(1, 5000)), new F2<Integer, Integer, Property>() {

public Property f(final Integer size, final Integer range) {

return bool(range > size).implies(new Generator().generate(size,

range).size() == size);

}

});

The problem here is that the generate method is still called with

invalid arguments, but that isn't allowed to happen. I tried to use

Gen.sized to replace Gen.choose, but can't figure out how to create a

tuple based on that.

Any ideas how to express those preconditions with Reductio?

Thanks

Jörn

Jun 5, 2008, 10:06:40 AM6/5/08

to redu...@googlegroups.com

Hi,

I guess you can do this in two ways, the second better than the first:

1. To ensure the second is always greater than the first, make the second be between 1001 and 5000 instead of between 1 and 5000.

2. As the generation of the second necessarily depends on the first, generate them together. Something like:

Property p = property(arbitrary(new F0<Pair<Integer, Integer>>() {

public Pair<Integer, Integer> f() {

int a;

return pair(a=random.nextInt(1000), a+1+random.nextInt(1000)); } },

new F1<Integer, Property>() {

public Property f(final Pair<Integer, Integer> sizeAndRange) {

return prop(new Generator().generate(sizeAndRange._1, sizeAndRange._2).size() ==

sizeAndRange.size()); } } );

I guess you can do this in two ways, the second better than the first:

1. To ensure the second is always greater than the first, make the second be between 1001 and 5000 instead of between 1 and 5000.

2. As the generation of the second necessarily depends on the first, generate them together. Something like:

Property p = property(arbitrary(new F0<Pair<Integer, Integer>>() {

public Pair<Integer, Integer> f() {

int a;

return pair(a=random.nextInt(1000), a+1+random.nextInt(1000)); } },

new F1<Integer, Property>() {

public Property f(final Pair<Integer, Integer> sizeAndRange) {

return prop(new Generator().generate(sizeAndRange._1, sizeAndRange._2).size() ==

sizeAndRange.size()); } } );

2008/6/5 Jörn Zaefferer <joern.z...@googlemail.com>:

Jun 5, 2008, 11:11:46 AM6/5/08

to Reductio

Thanks for the answer Ricky. I can't get it working though: I don't

have an F0 interface on my classpath, nor Pair. Where do these come

from?

Implementing those myself shouldn't be necessary when using

Reductio...

Jörn

On Jun 5, 4:06 pm, "Ricky Clarkson" <ricky.clark...@gmail.com> wrote:

> Hi,

>

> I guess you can do this in two ways, the second better than the first:

>

> 1. To ensure the second is always greater than the first, make the second be

> between 1001 and 5000 instead of between 1 and 5000.

> 2. As the generation of the second necessarily depends on the first,

> generate them together. Something like:

>

> Property p = property(arbitrary(new F0<Pair<Integer, Integer>>() {

> public Pair<Integer, Integer> f() {

> int a;

> return pair(a=random.nextInt(1000), a+1+random.nextInt(1000)); } },

> new F1<Integer, Property>() {

> public Property f(final Pair<Integer, Integer> sizeAndRange) {

> return prop(new Generator().generate(sizeAndRange._1,

> sizeAndRange._2).size() ==

> sizeAndRange.size()); } } );

>

> 2008/6/5 Jörn Zaefferer <joern.zaeffe...@googlemail.com>:

have an F0 interface on my classpath, nor Pair. Where do these come

from?

Implementing those myself shouldn't be necessary when using

Reductio...

Jörn

On Jun 5, 4:06 pm, "Ricky Clarkson" <ricky.clark...@gmail.com> wrote:

> Hi,

>

> I guess you can do this in two ways, the second better than the first:

>

> 1. To ensure the second is always greater than the first, make the second be

> between 1001 and 5000 instead of between 1 and 5000.

> 2. As the generation of the second necessarily depends on the first,

> generate them together. Something like:

>

> Property p = property(arbitrary(new F0<Pair<Integer, Integer>>() {

> public Pair<Integer, Integer> f() {

> int a;

> return pair(a=random.nextInt(1000), a+1+random.nextInt(1000)); } },

> new F1<Integer, Property>() {

> public Property f(final Pair<Integer, Integer> sizeAndRange) {

> return prop(new Generator().generate(sizeAndRange._1,

> sizeAndRange._2).size() ==

> sizeAndRange.size()); } } );

>

Jun 5, 2008, 12:58:11 PM6/5/08

to redu...@googlegroups.com

I apologise. I invented F0 and Pair and didn't look at what Reductio
and Functional Java provide. I could say I left that as an exercise
for the reader, but really I was just being lazy and hoping you
understood :)

Anyway, this is the first time I've used Reductio or Functional Java, so although this compiles and works fine, Tony probably has some things to say about it..

All it does is test that the second int is always bigger than the first though, so you'll have to adapt it to your case.

import static reductio.Arbitrary.arbitrary;

import reductio.Arbitrary;

import reductio.Gen;

import reductio.Rand;

import reductio.Property;

import static reductio.Property.prop;

import static reductio.Property.property;

import static reductio.CheckResult.summary;

import fj.F;

import static fj.P.p;

import fj.P2;

class Main {

public static void main(String[] args) {

Gen<P2<Integer, Integer>> gen = Gen.gen(new F<Integer, F<Rand, P2<Integer, Integer>>>() {

public F<Rand, P2<Integer, Integer>> f(Integer num) { return new F<Rand, P2<Integer, Integer>>() {

public P2<Integer, Integer> f(Rand rand) { int a;

return p(a = rand.choose(1,1000), rand.choose(a + 1, a + 1000)); } }; } });

Arbitrary<P2<Integer, Integer>> arb = arbitrary(gen);

Property p = property(arb, new F<P2<Integer, Integer>, Property>() { public Property f(P2<Integer, Integer> pair) {

return prop(pair._2() > pair._1()); } } );

summary.println(p.check()); } }

Anyway, this is the first time I've used Reductio or Functional Java, so although this compiles and works fine, Tony probably has some things to say about it..

All it does is test that the second int is always bigger than the first though, so you'll have to adapt it to your case.

import static reductio.Arbitrary.arbitrary;

import reductio.Arbitrary;

import reductio.Gen;

import reductio.Rand;

import reductio.Property;

import static reductio.Property.prop;

import static reductio.Property.property;

import static reductio.CheckResult.summary;

import fj.F;

import static fj.P.p;

import fj.P2;

class Main {

public static void main(String[] args) {

Gen<P2<Integer, Integer>> gen = Gen.gen(new F<Integer, F<Rand, P2<Integer, Integer>>>() {

public F<Rand, P2<Integer, Integer>> f(Integer num) { return new F<Rand, P2<Integer, Integer>>() {

public P2<Integer, Integer> f(Rand rand) { int a;

return p(a = rand.choose(1,1000), rand.choose(a + 1, a + 1000)); } }; } });

Arbitrary<P2<Integer, Integer>> arb = arbitrary(gen);

Property p = property(arb, new F<P2<Integer, Integer>, Property>() { public Property f(P2<Integer, Integer> pair) {

return prop(pair._2() > pair._1()); } } );

summary.println(p.check()); } }

2008/6/5 Jörn Zaefferer <joern.z...@googlemail.com>:

Jun 5, 2008, 4:40:34 PM6/5/08

to redu...@googlegroups.com

-----BEGIN PGP SIGNED MESSAGE-----

Hash: SHA1

Hash: SHA1

Hi Jörn,

I will answer your question in a general sense, since it may be

helpful for others in other settings; I hope you don't mind.

First, let's take a look at the truth table for logical implication:

p q p -> q

0 0 1

1 0 0

0 1 1

1 1 1

We see here that if p is false, then the value for the equation can be

determined without inspecting q (it's true!). This is a bit like &&

and || that are also lazy in their second argument. We want the same

for 'implies' so that the expression that is used for the value of 'q'

is not necessarily evaluated. Unfortunately, Java makes this a little

difficult, so you'll find two versions of the implies method. The one

you have used will evaluate both sides of the equation regardless but

is slightly easier to use.

Imagine a Java && that did this:

if(s != null && !s.isEmpty()) // ugh if s == null, we will get a NPE.

So, to actually answer your question; there is a version of 'implies'

that accepts a P1<Property> [1] and you can get a Property from a

boolean using the prop function [2]. (By the way, is Generator your

own type?)

return bool(range > size).implies(new P1<Property>() {

public Property _1() {

return prop(new Generator().generate(size, range).size() == size);

}

}

I hope this helps Jörn, but if not, please feel free to ask for more

clarification.

PS: I saw your comment on my blog, but Rickard beat me to answering :)

[1]

http://projects.workingmouse.com/public/reductio/artifacts/2.2//javadoc/reductio/Bool.html#implies(fj.P1)

[2]

http://projects.workingmouse.com/public/reductio/artifacts/2.2//javadoc/reductio/Property.html#prop(boolean)

- --

Tony Morris

http://tmorris.net/

-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1.4.6 (GNU/Linux)

Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFISE9CmnpgrYe6r60RAtpJAKC5PhSrHZ5BYhZbh1mIEyX5HZu6NgCdFu1K

PLLNZx+bObGo/qvLortFpck=

=iaM8

-----END PGP SIGNATURE-----

Jun 5, 2008, 4:58:29 PM6/5/08

to redu...@googlegroups.com

-----BEGIN PGP SIGNED MESSAGE-----

Hash: SHA1

Hash: SHA1

Ricky Clarkson wrote:

> I apologise. I invented F0 and Pair and didn't look at what

> Reductio and Functional Java provide. I could say I left that as an

> exercise for the reader, but really I was just being lazy and hoping

> you understood :)

Thanks Ricky for taking care of things while I was snoozing ;)

Functional Java provide fj.P1 and fj.P2 respectively for this scenario.

I'd also like add that Scala permits call-by-name function values, so

this problem does not pop up. Also, it allows non-alphanumeric method

names, so instead of 'implies' the method is called -> The scaladoc

for this function is here:

Note the annotation (=>) on the argument denoting its evaluation strategy.

You can see an example of the use of the -> method here:

http://reductiotest.org/examples/scala#IntegerOverflow

- --

Tony Morris

http://tmorris.net/

-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1.4.6 (GNU/Linux)

Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFISFN0mnpgrYe6r60RAiYQAKCK4vOAr0I4U/uG4GUCDakM5DZwBgCfakmz

WhVmaFc20dKMKKOi4zrFOPI=

=fZT1

-----END PGP SIGNATURE-----

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu