content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE TypeApplications #-}
  {-|
  Module      :  HsLua.Class.PeekableTests
  Copyright   :  © 2017-2024 Albert Krewinkel
  License     :  MIT
  
  Maintainer  :  Albert Krewinkel <tarleb@hslua.org>
  Stability   :  stable
  Portability :  portable
  
  Test for the conversion of lua values to haskell values.
  -}
  module HsLua.Class.PeekableTests (tests) where
  
  import Data.ByteString (ByteString)
  import HsLua.Class.Peekable
  import HsLua.Core as Lua
  import Test.Tasty.HsLua ( (=:), (?:), pushLuaExpr, shouldBeResultOf
                         , shouldBeErrorMessageOf )
  import Test.Tasty (TestTree, testGroup)
  
  -- | Specifications for Attributes parsing functions.
  tests :: TestTree
  tests = testGroup "Peekable"
    [ testGroup "Bool"
      ["literal true is truthy" ?: do
          pushLuaExpr @Lua.Exception "true"
          peek top
  
      , "0 as a non-nil value is truthy" ?: do
          pushnumber @Lua.Exception 0
          peek top
  
      , "nil is falsy" ?: do
          pushnil @Lua.Exception
          not <$> peek top
      ]
  
    , testGroup "Lua.Integer"
      [ "integer can be peeked" =:
        (5 :: Lua.Integer) `shouldBeResultOf` do
          pushnumber 5.0
          peek top
      ]
  
    , testGroup "Prelude.Integer"
      [ "small integer can be peeked" =:
        (23 :: Prelude.Integer) `shouldBeResultOf` do
          pushnumber 23
          peek top
  
      , "very large integer can be peeked" =:
        (10000000000000000000001 :: Prelude.Integer) `shouldBeResultOf` do
          pushstring "10000000000000000000001"
          peek top
      ]
  
    , testGroup "error handling"
      [ "error is thrown if boolean is given instead of stringy value" =:
        "string expected, got boolean" `shouldBeErrorMessageOf` do
          pushboolean False
          peek top :: Lua ByteString
  
      , "floating point numbers cannot be peeked as integer" =:
        "integer expected, got number" `shouldBeErrorMessageOf` do
          pushnumber 23.1
          peek top :: Lua Lua.Integer
  
      , "booleans cannot be retrieved as numbers" =:
        "number expected, got boolean" `shouldBeErrorMessageOf` do
          pushboolean False
          peek top :: Lua Lua.Number
  
      , "list cannot be read if a peeking at list element fails" =:
        ("number expected, got boolean" ++
         "\n\twhile retrieving index 4" ++
         "\n\twhile retrieving list")
        `shouldBeErrorMessageOf` do
          pushLuaExpr "{1, 5, 23, true, 42}"
          peek top :: Lua [Lua.Number]
  
      , "stack is unchanged if getting a list fails" =:
        0 `shouldBeResultOf` do
          pushLuaExpr "{true, 1, 1, 2, 3, 5, 8}"
          topBefore <- gettop
          _ <- peek top :: Lua [Bool]
          topAfter <- gettop
          return (topAfter - topBefore)
  
      , "stack is unchanged if getting key-value pairs fails" =:
        0 `shouldBeResultOf` do
          pushLuaExpr "{foo = 'bar', baz = false}"
          topBefore <- gettop
          _ <- try (peek top :: Lua [(String, String)])
          topAfter <- gettop
          return (topAfter - topBefore)
      ]
    ]
  