packages feed

hspec-megaparsec (empty) → 0.1.0

raw patch · 7 files changed

+403/−0 lines, 7 filesdep +basedep +hspecdep +hspec-expectationssetup-changed

Dependencies added: base, hspec, hspec-expectations, hspec-megaparsec, megaparsec

Files

+ CHANGELOG.md view
@@ -0,0 +1,3 @@+## Hspec Megaparsec 0.1.0++* Initial release.
+ LICENSE.md view
@@ -0,0 +1,28 @@+Copyright © 2016 Mark Karpov++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice,+  this list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright+  notice, this list of conditions and the following disclaimer in the+  documentation and/or other materials provided with the distribution.++* Neither the name Mark Karpov nor the names of contributors may be used to+  endorse or promote products derived from this software without specific+  prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “AS IS” AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN+NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,20 @@+# Hspec Megaparsec++[![License BSD3](https://img.shields.io/badge/license-BSD3-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause)+[![Hackage](https://img.shields.io/hackage/v/hspec-megaparsec.svg?style=flat)](https://hackage.haskell.org/package/hspec-megaparsec)+[![Stackage Nightly](http://stackage.org/package/hspec-megaparsec/badge/nightly)](http://stackage.org/nightly/package/hspec-megaparsec)+[![Build Status](https://travis-ci.org/mrkkrp/hspec-megaparsec.svg?branch=master)](https://travis-ci.org/mrkkrp/hspec-megaparsec)+[![Coverage Status](https://coveralls.io/repos/mrkkrp/hspec-megaparsec/badge.svg?branch=master&service=github)](https://coveralls.io/github/mrkkrp/hspec-megaparsec?branch=master)++The package provides utilities for testing+[`Megaparsec`](https://hackage.haskell.org/package/megaparsec) parsers with with+[`Hspec`](https://hackage.haskell.org/package/hspec).++Consult Haddocks for usage, which should be trivial. Also see test suite of+this package.++## License++Copyright © 2016 Mark Karpov++Distributed under BSD 3 clause license.
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ Test/Hspec/Megaparsec.hs view
@@ -0,0 +1,190 @@+-- |+-- Module      :  Test.Hspec.Megaparsec+-- Copyright   :  © 2016 Mark Karpov+-- License     :  BSD 3 clause+--+-- Maintainer  :  Mark Karpov <markkarpov@openmailbox.org>+-- Stability   :  experimental+-- Portability :  portable+--+-- Utility functions for testing Megaparsec parsers with Hspec.++module Test.Hspec.Megaparsec+  ( -- * Basic expectations+    shouldParse+  , parseSatisfies+  , shouldSucceedOn+  , shouldFailOn+    -- * Testing of error messages+  , shouldFailWith+    -- * Incremental parsing+  , failsLeaving+  , succeedsLeaving+  , initialState )+where++import Control.Monad (unless)+import Test.Hspec.Expectations+import Text.Megaparsec+import Text.Megaparsec.Pos (initialPos, defaultTabWidth)++----------------------------------------------------------------------------+-- Basic expectations++-- | Create an expectation by saying what the result should be.+--+-- > parse letterChar "" "x" `shouldParse` 'x'++shouldParse :: (Eq a, Show a)+  => Either ParseError a+     -- ^ Result of parsing as returned by function like 'parse'+  -> a                 -- ^ Desired result+  -> Expectation+r `shouldParse` v = case r of+  Left e -> expectationFailure $ "expected: " ++ show v +++    "\nbut parsing failed with error:\n" ++ showParseError e+  Right x -> unless (x == v) . expectationFailure $+    "expected: " ++ show v ++ "\nbut got: " ++ show x++-- | Create an expectation by saying that the parser should successfully+-- parse a value and that the value should satisfy some predicate.+--+-- > parse (many punctuationChar) "" "?!!" `parseSatisfies` ((== 3) . length)++parseSatisfies :: Show a+  => Either ParseError a+     -- ^ Result of parsing as returned by function like 'parse'+  -> (a -> Bool)       -- ^ Predicate+  -> Expectation+r `parseSatisfies` p = case r of+  Left e -> expectationFailure $+    "expected a parsed value to check against the predicate" +++    "\nbut parsing failed with error:\n" ++ showParseError e+  Right x -> unless (p x) . expectationFailure $+    "the value did not satisfy the predicate: " ++ show x++-- | Check that a parser fails on some given input.+--+-- > parse (char 'x') "" `shouldFailOn` "a"++shouldFailOn :: (Show a, Stream s t)+  => (s -> Either ParseError a)+     -- ^ Parser that takes stream and produces result or error message+  -> s                 -- ^ Input that the parser should fail on+  -> Expectation+p `shouldFailOn` s = shouldFail (p s)++-- | Check that a parser succeeds on some given input.+--+-- > parse (char 'x') "" `shouldSucceedOn` "x"++shouldSucceedOn :: (Show a, Stream s t)+  => (s -> Either ParseError a)+     -- ^ Parser that takes stream and produces result or error message+  -> s                 -- ^ Input that the parser should succeed on+  -> Expectation+p `shouldSucceedOn` s = shouldSucceed (p s)++----------------------------------------------------------------------------+-- Testing of error messages++-- | Create an expectation that parser should fail producing certain+-- 'ParseError'. Use functions from "Text.Megaparsec.Error" to construct+-- parse errors to check against. See "Text.Megaparsec.Pos" for functions to+-- construct textual positions.+--+-- > parse (char 'x') "" "b" `shouldFailWith`+-- >   newErrorMessages [Unexpected "'b'", Expected "'x'"] (initialPos "")++shouldFailWith :: Show a+  => Either ParseError a+  -> ParseError+  -> Expectation+r `shouldFailWith` e = case r of+  Left e' -> unless (e == e') . expectationFailure $+    "the parser is expected to fail with:\n" ++ showParseError e +++    "but it failed with:\n" ++ showParseError e+  Right v -> expectationFailure $+    "the parser is expected to fail, but it parsed: " ++ show v++----------------------------------------------------------------------------+-- Incremental parsing++-- | Check that a parser fails and leaves certain part of input+-- unconsumed. Use it with functions like 'runParser'' and 'runParserT''+-- that support incremental parsing.+--+-- > runParser' (many (char 'x') <* eof) (initialState "xxa")+-- >   `failsLeaving` "xxa"+--+-- See also: 'initialState'.++failsLeaving :: (Show a, Eq s, Show s, Stream s t)+  => (State s, Either ParseError a)+     -- ^ Parser that takes stream and produces result along with actual+     -- state information+  -> s                 -- ^ Part of input that should be left unconsumed+  -> Expectation+(st,r) `failsLeaving` s =+  shouldFail r >> checkUnconsumed s (stateInput st)++-- | Check that a parser succeeds and leaves certain part of input+-- unconsumed. Use it with functions like 'runParser'' and 'runParserT''+-- that support incremental parsing.+--+-- > runParser' (many (char 'x')) (initialState "xxa")+-- >   `succeedsLeaving` "a"+--+-- See also: 'initialState'.++succeedsLeaving :: (Show a, Eq s, Show s, Stream s t)+  => (State s, Either ParseError a)+     -- ^ Parser that takes stream and produces result along with actual+     -- state information+  -> s                 -- ^ Part of input that should be left unconsumed+  -> Expectation+(st,r) `succeedsLeaving` s =+  shouldSucceed r >> checkUnconsumed s (stateInput st)++-- | Given input for parsing, construct initial state for parser (that is,+-- with empty file name, default tab width and position at 1 line and 1+-- column).++initialState :: Stream s t => s -> State s+initialState s = State s (initialPos "") defaultTabWidth++----------------------------------------------------------------------------+-- Helpers++-- | Expectation that argument is result of a failed parser.++shouldFail :: Show a => Either ParseError a -> Expectation+shouldFail r = case r of+  Left _ -> return ()+  Right v -> expectationFailure $+    "the parser is expected to fail, but it parsed: " ++ show v++-- | Expectation that argument is result of a succeeded parser.++shouldSucceed :: Show a => Either ParseError a -> Expectation+shouldSucceed r = case r of+  Left e -> expectationFailure $+    "the parser is expected to succeed, but it failed with:\n" +++    showParseError e+  Right _ -> return ()++-- | Compare two streams for equality and in the case of mismatch report it.++checkUnconsumed :: (Eq s, Show s, Stream s t)+  => s                 -- ^ Expected unconsumed input+  -> s                 -- ^ Actual unconsumed input+  -> Expectation+checkUnconsumed e a = unless (e == a) . expectationFailure $+  "the parser is expected to leave unconsumed input: " ++ show e +++  "\nbut it left this: " ++ show a++-- | Render parse error in a way that is suitable for inserting it in test+-- suite report.++showParseError :: ParseError -> String+showParseError = unlines . fmap ("  " ++) . lines . show
+ hspec-megaparsec.cabal view
@@ -0,0 +1,82 @@+--+-- Cabal configuration for ‘hspec-megaparsec’.+--+-- Copyright © 2016 Mark Karpov+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions are+-- met:+--+-- * Redistributions of source code must retain the above copyright notice,+--   this list of conditions and the following disclaimer.+--+-- * Redistributions in binary form must reproduce the above copyright+--   notice, this list of conditions and the following disclaimer in the+--   documentation and/or other materials provided with the distribution.+--+-- * Neither the name Mark Karpov nor the names of contributors may be used+--   to endorse or promote products derived from this software without+--   specific prior written permission.+--+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “AS IS” AND ANY+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY+-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+-- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+-- POSSIBILITY OF SUCH DAMAGE.++name:                 hspec-megaparsec+version:              0.1.0+cabal-version:        >= 1.10+license:              BSD3+license-file:         LICENSE.md+author:               Mark Karpov <markkarpov@opmbx.org>+maintainer:           Mark Karpov <markkarpov@opmbx.org>+homepage:             https://github.com/mrkkrp/hspec-megaparsec+bug-reports:          https://github.com/mrkkrp/hspec-megaparsec/issues+category:             Testing, Parsing+synopsis:             Utility functions for testing Megaparsec parsers with Hspec+build-type:           Simple+description:          Utility functions for testing Megaparsec parsers with Hspec.+extra-source-files:   CHANGELOG.md+                    , README.md++flag dev+  description:        Turn on development settings.+  manual:             True+  default:            False++library+  build-depends:      base               >= 4.6 && < 5+                    , hspec-expectations >= 0.5+                    , megaparsec         >= 4.2+  exposed-modules:    Test.Hspec.Megaparsec+  if flag(dev)+    ghc-options:      -Wall -Werror+  else+    ghc-options:      -Wall+  default-language:   Haskell2010++test-suite tests+  main-is:            Main.hs+  hs-source-dirs:     tests+  type:               exitcode-stdio-1.0+  if flag(dev)+    ghc-options:      -Wall -Werror+  else+    ghc-options:      -Wall+  build-depends:      base               >= 4.6 && < 5+                    , hspec              >= 2.0+                    , hspec-expectations >= 0.5+                    , hspec-megaparsec   >= 0.1+                    , megaparsec         >= 4.2+  default-language:   Haskell2010++source-repository head+  type:               git+  location:           https://github.com/mrkkrp/hspec-megaparsec.git
+ tests/Main.hs view
@@ -0,0 +1,74 @@+--+-- Hspec Megaparsec tests.+--+-- Copyright © 2016 Mark Karpov+--+-- Redistribution and use in source and binary forms, with or without+-- modification, are permitted provided that the following conditions are+-- met:+--+-- * Redistributions of source code must retain the above copyright notice,+--   this list of conditions and the following disclaimer.+--+-- * Redistributions in binary form must reproduce the above copyright+--   notice, this list of conditions and the following disclaimer in the+--   documentation and/or other materials provided with the distribution.+--+-- * Neither the name Mark Karpov nor the names of contributors may be used+--   to endorse or promote products derived from this software without+--   specific prior written permission.+--+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS “AS IS” AND ANY+-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY+-- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+-- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+-- ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+-- POSSIBILITY OF SUCH DAMAGE.++{-# LANGUAGE CPP #-}++module Main (main) where++import Test.Hspec+import Test.Hspec.Megaparsec+import Text.Megaparsec+import Text.Megaparsec.Error (newErrorMessages)+import Text.Megaparsec.Pos (initialPos)++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative ((<*))+#endif++-- | Toy tests, just an example of usage.++main :: IO ()+main = hspec $ do+  describe "shouldParse" $+    it "works" $+      parse letterChar "" "x" `shouldParse` 'x'+  describe "parseSatisfies" $+    it "works" $+      parse (many punctuationChar) "" "?!!" `parseSatisfies` ((== 3) . length)+  describe "shouldFailOn" $+    it "works" $+      parse (char 'x') "" `shouldFailOn` "a"+  describe "shouldSucceedOn" $+    it "works" $+      parse (char 'x') "" `shouldSucceedOn` "x"+  describe "shouldFailWith" $+    it "works" $+      parse (char 'x') "" "b" `shouldFailWith`+        newErrorMessages [Unexpected "'b'", Expected "'x'"] (initialPos "")+  describe "failsLeaving" $+    it "works" $+      runParser' (many (char 'x') <* eof) (initialState "xxa")+        `failsLeaving` "xxa"+  describe "succeedsLeaving" $+    it "works" $+      runParser' (many (char 'x')) (initialState "xxa")+        `succeedsLeaving` "a"