Skip to content

Commit 324b2f6

Browse files
committed
Merge pull request #7 from jdegoes/master
add arb instances for string & alpha num string, migrate to gulp, add sized generators
2 parents af98f14 + 0302e8a commit 324b2f6

File tree

9 files changed

+257
-118
lines changed

9 files changed

+257
-118
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
/bower_components/
66
/tmp/
77
/node_modules/
8+
/test/

Gruntfile.js

Lines changed: 0 additions & 30 deletions
This file was deleted.

README.md

100644100755
Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Types
66

7+
newtype AlphaNumString where
8+
AlphaNumString :: String -> AlphaNumString
9+
710
type QC a = forall eff. Eff (err :: Exception, random :: Random, trace :: Trace | eff) a
811

912
data Result where
@@ -25,6 +28,8 @@
2528

2629
### Type Class Instances
2730

31+
instance arbAlphaNumString :: Arbitrary AlphaNumString
32+
2833
instance arbArray :: (Arbitrary a) => Arbitrary [a]
2934

3035
instance arbBoolean :: Arbitrary Boolean
@@ -33,6 +38,10 @@
3338

3439
instance arbNumber :: Arbitrary Number
3540

41+
instance arbString :: Arbitrary String
42+
43+
instance coarbAlphaNumString :: CoArbitrary AlphaNumString
44+
3645
instance coarbArray :: (CoArbitrary a) => CoArbitrary [a]
3746

3847
instance coarbBoolean :: CoArbitrary Boolean
@@ -41,6 +50,8 @@
4150

4251
instance coarbNumber :: CoArbitrary Number
4352

53+
instance coarbString :: CoArbitrary String
54+
4455
instance showResult :: Show Result
4556

4657
instance testableBoolean :: Testable Boolean
@@ -60,52 +71,5 @@
6071

6172
quickCheckPure :: forall prop. (Testable prop) => Number -> Number -> prop -> [Result]
6273

63-
repeatable :: forall a b. (a -> Gen b) -> Gen (a -> b)
64-
65-
66-
## Module Test.QuickCheck.LCG
67-
68-
### Types
69-
70-
data Gen a where
71-
Gen :: LCG -> { newSeed :: LCG, value :: a } -> Gen a
72-
73-
type LCG = Number
74-
75-
76-
### Type Class Instances
77-
78-
instance applicativeGen :: Applicative Gen
79-
80-
instance applyGen :: Apply Gen
81-
82-
instance bindGen :: Bind Gen
83-
84-
instance functorGen :: Functor Gen
85-
86-
instance monadGen :: Monad Gen
87-
88-
89-
### Values
90-
91-
evalGen :: forall a. Gen a -> LCG -> a
92-
93-
float32ToInt32 :: Number -> Number
94-
95-
lcgC :: Number
96-
97-
lcgM :: Number
98-
99-
lcgN :: Number
100-
101-
lcgNext :: Number -> Number
102-
103-
lcgStep :: Gen Number
104-
105-
perturbGen :: forall a. Number -> Gen a -> Gen a
106-
107-
randomSeed :: forall eff. Eff (random :: Random | eff) Number
10874

109-
runGen :: forall a. Gen a -> LCG -> { newSeed :: LCG, value :: a }
11075

111-
uniform :: Gen Number

bower.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"name": "purescript-quickcheck",
3+
"version": "0.0.2",
34
"license": "MIT",
45
"ignore": [
56
"**/.*",
@@ -14,6 +15,9 @@
1415
],
1516
"dependencies": {
1617
"purescript-random": "*",
17-
"purescript-exceptions": "0.2.0"
18+
"purescript-exceptions": "0.2.0",
19+
"purescript-arrays": "*",
20+
"purescript-strings": "*",
21+
"purescript-math": "*"
1822
}
1923
}

gulpfile.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
'use strict'
2+
3+
var gulp = require('gulp')
4+
, purescript = require('gulp-purescript')
5+
, run = require('gulp-run')
6+
, runSequence = require('run-sequence')
7+
;
8+
9+
var paths = {
10+
src: 'src/**/*.purs',
11+
bowerSrc: [
12+
'bower_components/purescript-*/src/**/*.purs',
13+
'bower_components/purescript-*/src/**/*.purs.hs'
14+
],
15+
dest: '',
16+
docs: {
17+
'Test.QuickCheck': {
18+
dest: 'README.md',
19+
src: 'src/Test/QuickCheck.purs'
20+
},
21+
'Test.QuickCheck.*': {
22+
dest: 'src/Test/QuickCheck/README.md',
23+
src: 'src/Test/QuickCheck/*.purs'
24+
}
25+
},
26+
test: 'examples/*.purs'
27+
};
28+
29+
var options = {
30+
test: {
31+
main: 'PreludeTests',
32+
output: 'test/test.js'
33+
}
34+
};
35+
36+
function compile (compiler, src, opts) {
37+
var psc = compiler(opts);
38+
psc.on('error', function(e) {
39+
console.error(e.message);
40+
psc.end();
41+
});
42+
return gulp.src(src.concat(paths.bowerSrc))
43+
.pipe(psc)
44+
.pipe(gulp.dest(paths.dest));
45+
};
46+
47+
function docs (target) {
48+
return function() {
49+
var docgen = purescript.docgen();
50+
docgen.on('error', function(e) {
51+
console.error(e.message);
52+
docgen.end();
53+
});
54+
return gulp.src(paths.docs[target].src)
55+
.pipe(docgen)
56+
.pipe(gulp.dest(paths.docs[target].dest));
57+
}
58+
}
59+
60+
function sequence () {
61+
var args = [].slice.apply(arguments);
62+
return function() {
63+
runSequence.apply(null, args);
64+
}
65+
}
66+
67+
gulp.task('browser', function() {
68+
return compile(purescript.psc, [paths.src].concat(paths.bowerSrc), {})
69+
});
70+
71+
gulp.task('make', function() {
72+
return compile(purescript.pscMake, [paths.src].concat(paths.bowerSrc), {})
73+
});
74+
75+
gulp.task('test', function() {
76+
return compile(purescript.psc, [paths.src, paths.test].concat(paths.bowerSrc), options.test)
77+
.pipe(run('node').exec());
78+
});
79+
80+
gulp.task('docs-Test.QuickCheck', docs('Test.QuickCheck'));
81+
gulp.task('docs-Test.QuickCheck.*', docs('Test.QuickCheck.*'));
82+
83+
gulp.task('docs', ['docs-Test.QuickCheck', 'docs-Test.QuickCheck.*']);
84+
85+
gulp.task('watch-browser', function() {
86+
gulp.watch(paths.src, sequence('browser', 'docs'));
87+
});
88+
89+
gulp.task('watch-make', function() {
90+
gulp.watch(paths.src, sequence('make', 'docs'));
91+
});
92+
93+
gulp.task('default', sequence('make', 'docs'));

package.json

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
{
2-
"private": true,
3-
"dependencies": {
4-
"grunt": "~0.4.4",
5-
"grunt-purescript": "~0.5.1",
6-
"grunt-contrib-clean": "~0.5.0"
2+
"name": "purescript-quickcheck",
3+
"version": "0.0.2",
4+
"license": "MIT",
5+
"repository": "[email protected]:purescript-contrib/purescript-quickcheck.git",
6+
7+
"devDependencies": {
8+
"gulp": "^3.8.8",
9+
"gulp-purescript": "0.0.10",
10+
"gulp-run": "^1.6.4",
11+
"run-sequence": "^0.3.6"
712
}
8-
}
13+
}

src/Test/QuickCheck.purs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
module Test.QuickCheck where
22

33
import Debug.Trace
4+
import Control.Bind
45
import Control.Monad.Eff
56
import Control.Monad.Eff.Random
67
import Control.Monad.Eff.Exception
8+
import Data.Array
9+
import Math
10+
11+
import qualified Data.String as S
712

813
import Test.QuickCheck.LCG
914

15+
newtype AlphaNumString = AlphaNumString String
16+
1017
class Arbitrary t where
1118
arbitrary :: Gen t
1219

@@ -35,15 +42,32 @@ instance arbBoolean :: Arbitrary Boolean where
3542
return $ (n * 2) < 1
3643

3744
instance coarbBoolean :: CoArbitrary Boolean where
38-
coarbitrary true (Gen f) = Gen $ \l -> f (l + 1)
39-
coarbitrary false (Gen f) = Gen $ \l -> f (l + 2)
45+
coarbitrary true = perturbGen 1
46+
coarbitrary false = perturbGen 2
47+
48+
instance arbString :: Arbitrary String where
49+
arbitrary = do
50+
arrNum <- arbitrary
51+
return $ (S.joinWith "") $ S.fromCharCode <<< ((*) 65535) <$> arrNum
52+
53+
instance coarbString :: CoArbitrary String where
54+
coarbitrary s = coarbitrary $ (S.charCodeAt 0 <$> S.split "" s)
55+
56+
instance arbAlphaNumString :: Arbitrary AlphaNumString where
57+
arbitrary = do
58+
arrNum <- arbitrary
59+
return $ AlphaNumString <<< (S.joinWith "") $ lookup <$> arrNum where
60+
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
61+
62+
lookup x = S.charAt index chars where
63+
index = round $ x * (S.length chars - 1)
64+
65+
instance coarbAlphaNumString :: CoArbitrary AlphaNumString where
66+
coarbitrary (AlphaNumString s) = coarbitrary s
4067

4168
instance arbFunction :: (CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) where
4269
arbitrary = repeatable (\a -> coarbitrary a arbitrary)
4370

44-
repeatable :: forall a b. (a -> Gen b) -> Gen (a -> b)
45-
repeatable f = Gen $ \l -> { value: \a -> (runGen (f a) l).value, newSeed: l }
46-
4771
instance coarbFunction :: (Arbitrary a, CoArbitrary b) => CoArbitrary (a -> b) where
4872
coarbitrary f gen = do
4973
xs <- arbitrary
@@ -80,19 +104,20 @@ instance testableFunction :: (Arbitrary t, Testable prop) => Testable (t -> prop
80104
test (f t)
81105

82106
quickCheckPure :: forall prop. (Testable prop) => Number -> Number -> prop -> [Result]
83-
quickCheckPure seed n prop = evalGen (go n) seed
84-
where
85-
go n | n <= 0 = return []
86-
go n = do
87-
result <- test prop
88-
rest <- go (n - 1)
89-
return $ result : rest
107+
quickCheckPure s = quickCheckPure' {newSeed: s, size: 10} where
108+
quickCheckPure' st n prop = evalGen (go n) st
109+
where
110+
go n | n <= 0 = return []
111+
go n = do
112+
result <- test prop
113+
rest <- go (n - 1)
114+
return $ result : rest
90115

91116
type QC a = forall eff. Eff (trace :: Trace, random :: Random, err :: Exception | eff) a
92117

93118
quickCheck' :: forall prop. (Testable prop) => Number -> prop -> QC Unit
94119
quickCheck' n prop = do
95-
seed <- randomSeed
120+
seed <- random
96121
let results = quickCheckPure seed n prop
97122
let successes = countSuccesses results
98123
trace $ show successes ++ "/" ++ show n ++ " test(s) passed."

0 commit comments

Comments
 (0)