{-# 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