packages feed

greskell-core-1.0.0.1: test/Data/Greskell/GreskellSpec.hs

{-# LANGUAGE OverloadedStrings #-}
module Data.Greskell.GreskellSpec
    ( main
    , spec
    ) where

import qualified Data.Aeson                    as Aeson
import           Data.String                   (fromString)
import           Data.Text                     (Text, pack)
import           Test.Hspec
import           Test.QuickCheck               (property)

import           Data.Greskell.Greskell        (Greskell, false, list, number, string, toGremlin,
                                                true, unsafeFunCall, unsafeGreskell, value)

import           Data.Greskell.Test.QuickCheck ()

main :: IO ()
main = hspec spec

spec :: Spec
spec = do
  spec_literals
  spec_other

spec_other :: Spec
spec_other = do
  describe "unsafeGreskell" $ it "should be just a raw script text" $ property $ \t ->
    (toGremlin $ unsafeGreskell t) `shouldBe` t
  describe "Num" $ do
    specify "integer" $ do
      let x = 123 :: Greskell Int
      toGremlin x `shouldBe` "123"
    specify "negative integer" $ do
      let x = -56 :: Greskell Int
      toGremlin x `shouldBe` "-(56)"
    specify "operations" $ do
      let x = (30 + 15 * 20 - 10) :: Greskell Int
      toGremlin x `shouldBe` "((30)+((15)*(20)))-(10)"
    specify "abs, signum" $ do
      let x = (signum $ abs (-100)) :: Greskell Int
      toGremlin x  `shouldBe` "java.lang.Long.signum(java.lang.Math.abs(-(100)))"
  describe "Fractional" $ do
    specify "floating point literal" $ do
      let x = 92.12 :: Greskell Double
      (toGremlin x) `shouldBe` "2303.0/25"
    specify "operations" $ do
      let x = (100.5 * recip 30.0 / 20.2) :: Greskell Double
      toGremlin x `shouldBe` "((201.0/2)*(1.0/(30.0/1)))/(101.0/5)"
  describe "Monoid" $ do
    specify "mempty" $ do
      let got = mempty :: Greskell Text
      toGremlin got `shouldBe` "\"\""
    specify "mappend" $ do
      let got = (mappend "foo" "bar") :: Greskell Text
      toGremlin got `shouldBe` "(\"foo\")+(\"bar\")"
  describe "unsafeFunCall" $ do
    it "should make function call" $ do
      (toGremlin $ unsafeFunCall "fun" ["foo", "bar"]) `shouldBe` "fun(foo,bar)"

spec_literals :: Spec
spec_literals = do
  describe "string and fromString" $ do
    specify "empty" $ checkStringLiteral "" "\"\""
    specify "words" $ checkStringLiteral "hoge foo bar"  "\"hoge foo bar\""
    specify "escaped" $ checkStringLiteral "foo 'aaa \n \t \\ \"bar\"" "\"foo 'aaa \\n \\t \\\\ \\\"bar\\\"\""
  describe "list" $ do
    specify "empty" $ do
      toGremlin (list []) `shouldBe` "[]"
    specify "num" $ do
      toGremlin (list $ [(10 :: Greskell Int), 20, 30]) `shouldBe` "[10,20,30]"
    specify "list of lists" $ do
      toGremlin (list $ map list $ [[("" :: Greskell Text)], ["foo", "bar"], ["buzz"]])
        `shouldBe` "[[\"\"],[\"foo\",\"bar\"],[\"buzz\"]]"
  describe "boolean" $ do
    specify "true" $ do
      toGremlin true `shouldBe` "true"
    specify "false" $ do
      toGremlin false `shouldBe` "false"
  describe "number" $ do
    specify "zero" $ do
      toGremlin (number 0) `shouldBe` "0.0"
    specify "positive integer" $ do
      toGremlin (number 1234) `shouldBe` "1234.0"
    specify "negative integer" $ do
      toGremlin (number (-292)) `shouldBe` "-292.0"
    specify "positive floating" $ do
      toGremlin (number 32.123) `shouldBe` "32.123"
    specify "negative floating" $ do
      toGremlin (number (-0.0943)) `shouldBe` "-9.43e-2"
    specify "big positive integer" $ do
      toGremlin (number 3.23e9) `shouldBe` "3.23e9"
  describe "value" $ do
    specify "null" $ do
      toGremlin (value Aeson.Null) `shouldBe` "null"
    specify "bool" $ do
      toGremlin (value $ Aeson.Bool False) `shouldBe` "false"
    specify "integer" $ do
      toGremlin (value $ Aeson.Number 100) `shouldBe` "100.0"
    specify "floating-point number" $ do
      toGremlin (value $ Aeson.Number 10.23) `shouldBe` "10.23"
    specify "String" $ do
      toGremlin (value $ Aeson.String "foobar") `shouldBe` "\"foobar\""
    specify "empty Array" $ do
      toGremlin (value $ Aeson.toJSON ([] :: [Int])) `shouldBe` "[]"
    specify "non-empty Array" $ do
      toGremlin (value $ Aeson.toJSON [(5 :: Int), 6, 7]) `shouldBe` "[5.0,6.0,7.0]"
    specify "empty Object" $ do
      toGremlin (value $ Aeson.object []) `shouldBe` "[:]"


checkStringLiteral :: String -> Text -> Expectation
checkStringLiteral input expected = do
  let input' = fromString input :: Greskell Text
  (toGremlin $ input') `shouldBe` expected
  (toGremlin $ string $ pack input) `shouldBe` expected