2019-06-11 01:53:20 +03:00
|
|
|
{-# OPTIONS_GHC -O0 #-}
|
2019-06-16 14:00:47 +03:00
|
|
|
{-# LANGUAGE ImplicitParams #-}
|
2018-03-14 02:19:26 +03:00
|
|
|
module Analysis.Ruby.Spec (spec) where
|
|
|
|
|
2019-06-12 19:52:11 +03:00
|
|
|
import Control.Abstract (Declaration (..), ScopeError (..))
|
2018-12-05 20:12:13 +03:00
|
|
|
import Control.Effect.Resumable (SomeError (..))
|
|
|
|
import Data.Abstract.Evaluatable
|
2018-06-26 00:28:35 +03:00
|
|
|
import qualified Data.Abstract.ModuleTable as ModuleTable
|
2018-12-05 20:12:13 +03:00
|
|
|
import Data.Abstract.Number as Number
|
|
|
|
import Data.Abstract.Value.Concrete as Value
|
2018-04-24 02:47:13 +03:00
|
|
|
import qualified Data.Language as Language
|
2018-12-05 20:12:13 +03:00
|
|
|
import Data.Sum
|
2018-03-14 02:19:26 +03:00
|
|
|
|
|
|
|
import SpecHelpers
|
|
|
|
|
|
|
|
|
2019-06-12 20:53:59 +03:00
|
|
|
spec :: (?session :: TaskSession) => Spec
|
2019-06-20 00:22:09 +03:00
|
|
|
spec = do
|
2018-03-26 21:09:22 +03:00
|
|
|
describe "Ruby" $ do
|
2018-06-26 00:28:35 +03:00
|
|
|
it "evaluates require_relative" $ do
|
2018-11-29 02:48:23 +03:00
|
|
|
(scopeGraph, (heap, res)) <- evaluate ["main.rb", "foo.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "main.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (scopeAndFrame, value))) -> do
|
2018-12-07 23:23:03 +03:00
|
|
|
value `shouldBe` Value.Integer (Number.Integer 1)
|
2019-06-16 18:14:03 +03:00
|
|
|
SpecHelpers.lookupDeclaration "foo" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
2018-06-26 00:28:35 +03:00
|
|
|
other -> expectationFailure (show other)
|
|
|
|
|
|
|
|
it "evaluates load" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(scopeGraph, (heap, res)) <- evaluate ["load.rb", "foo.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "load.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (scopeAndFrame, value))) -> do
|
2018-12-07 23:23:03 +03:00
|
|
|
value `shouldBe` Value.Integer (Number.Integer 1)
|
2019-06-16 18:14:03 +03:00
|
|
|
SpecHelpers.lookupDeclaration "foo" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
2018-06-26 00:28:35 +03:00
|
|
|
other -> expectationFailure (show other)
|
|
|
|
|
|
|
|
it "evaluates load with wrapper" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["load-wrap.rb", "foo.rb"]
|
2019-03-28 01:57:55 +03:00
|
|
|
res `shouldBe` Left (SomeError (inject @(BaseError (ScopeError Precise)) (BaseError (ModuleInfo "load-wrap.rb" Language.Ruby mempty) (Span (Pos 3 1) (Pos 3 7)) (LookupPathError (Declaration "foo")))))
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "evaluates subclass" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(scopeGraph, (heap, res)) <- evaluate ["subclass.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "subclass.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (scopeAndFrame, value))) -> do
|
2018-12-07 23:23:03 +03:00
|
|
|
value `shouldBe` String "\"<bar>\""
|
2019-06-16 18:14:03 +03:00
|
|
|
SpecHelpers.lookupDeclaration "Bar" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
|
|
|
SpecHelpers.lookupDeclaration "Foo" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
2018-12-05 20:44:52 +03:00
|
|
|
SpecHelpers.lookupMembers "Bar" Superclass scopeAndFrame heap scopeGraph `shouldBe` Just ["baz", "foo", "inspect"]
|
2018-06-26 00:28:35 +03:00
|
|
|
other -> expectationFailure (show other)
|
|
|
|
|
|
|
|
it "evaluates modules" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(scopeGraph, (heap, res)) <- evaluate ["modules.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "modules.rb" <$> res of
|
2019-06-15 07:53:02 +03:00
|
|
|
Right (Just (Module _ (scopeAndFrame, _))) -> do
|
2019-06-16 18:14:03 +03:00
|
|
|
SpecHelpers.lookupDeclaration "Bar" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
2018-06-26 00:28:35 +03:00
|
|
|
other -> expectationFailure (show other)
|
|
|
|
|
|
|
|
it "handles break correctly" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["break.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "break.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` Value.Integer (Number.Integer 3)
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "handles next correctly" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["next.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "next.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` Value.Integer (Number.Integer 8)
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "calls functions with arguments" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["call.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "call.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` Value.Integer (Number.Integer 579)
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "evaluates early return statements" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["early-return.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "early-return.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` Value.Integer (Number.Integer 123)
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "has prelude" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["preluded.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "preluded.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` String "\"<foo>\""
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "evaluates __LINE__" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(_, (_, res)) <- evaluate ["line.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "line.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (_, value))) -> value `shouldBe` Value.Integer (Number.Integer 4)
|
2018-12-05 20:12:13 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-06-26 00:28:35 +03:00
|
|
|
|
|
|
|
it "resolves builtins used in the prelude" $ do
|
2018-11-29 03:59:05 +03:00
|
|
|
(scopeGraph, (heap, res)) <- evaluate ["puts.rb"]
|
2018-06-26 00:28:35 +03:00
|
|
|
case ModuleTable.lookup "puts.rb" <$> res of
|
2018-12-11 21:07:45 +03:00
|
|
|
Right (Just (Module _ (scopeAndFrame, value))) -> do
|
2018-12-07 23:23:03 +03:00
|
|
|
value `shouldBe` Unit
|
2019-06-16 18:14:03 +03:00
|
|
|
SpecHelpers.lookupDeclaration "puts" scopeAndFrame heap scopeGraph `shouldSatisfy` isJust
|
2018-06-26 00:28:35 +03:00
|
|
|
other -> expectationFailure (show other)
|
2018-05-10 18:03:42 +03:00
|
|
|
|
2018-03-14 02:19:26 +03:00
|
|
|
where
|
|
|
|
fixtures = "test/fixtures/ruby/analysis/"
|
2018-06-22 22:45:42 +03:00
|
|
|
evaluate = evalRubyProject . map (fixtures <>)
|
2019-06-12 20:53:59 +03:00
|
|
|
evalRubyProject = testEvaluating <=< evaluateProject' ?session (Proxy :: Proxy 'Language.Ruby) rubyParser
|