{-| Module : Main (Test) Description : Test suite for Lazyboy Copyright : (c) Rose 2019 License : BSD3 Maintainer : rose@lain.org.uk Stability : experimental Portability : POSIX A test suite for Lazyboy. -} import Control.Exception (evaluate) import Lazyboy import Lazyboy.Target.ASM import Test.Hspec disallow cmd = evaluate cmd `shouldThrow` anyException main :: IO () main = hspec $ do describe "Lazyboy.IO" $ do context "when asked to pack an LCDControl" $ do it "packs an LCDControl of all False values to 0" $ do pack defaultLCDControl `shouldBe` 0 it "packs an LCDControl with background and display enabled to 129" $ do pack (LCDControl True False False False False False False True) `shouldBe` 129 it "packs other LCDControls correctly" $ do pack (defaultLCDControl { lcdEnableObjects = True }) `shouldBe` 2 context "when asked to pack a BackgroundPalette" $ do it "packs a BackgroundPalette of all-black to 255" $ do pack (BackgroundPalette Black Black Black Black) `shouldBe` 255 it "packs a BackgroundPalette of all-white to 0" $ do pack (BackgroundPalette White White White White) `shouldBe` 0 it "correctly packs other BackgroundPalettes" $ do pack (BackgroundPalette White Light White White) `shouldBe` 16 describe "Lazyboy.Types.execLazyboy" $ do it "compiles nested sequences in order" $ do let sequence = execLazyboy $ do write (Address 0x2000) 0x97 write (Address 0x1000) 0x98 sequence `shouldBe` [LDrrnn HL (Address 0x2000), LDHLn 0x97, LDrrnn HL (Address 0x1000), LDHLn 0x98] describe "Lazyboy.Control" $ do describe "cond" $ do it "correctly implements conditionals" $ do let program = execLazyboy $ do cond NonZero $ do freeze program `shouldBe` [JPif NonZero $ Name $ Local 1, LABEL $ Global 2, DI, HALT, JP $ Name $ Global 2, LABEL $ Local 1] it "handles nested conditionals correctly" $ do let program = execLazyboy $ do cond Zero $ do cond NonZero $ do freeze program `shouldBe` [ JPif Zero $ Name $ Local 1 , JPif NonZero $ Name $ Local 2 , LABEL $ Global 3 , DI , HALT , JP $ Name $ Global 3 , LABEL $ Local 2 , LABEL $ Local 1 ] describe "withLabel" $ do it "creates an appropriately formatted global label" $ do let program = map show $ execLazyboy $ do withLabel $ \label -> do write (Address 0xC000) 0x97 program `shouldBe` [ "L1:" , "ld HL, $C000" , "ld [HL], 151" ] describe "withLocalLabel" $ do it "creates an appropriately formatted local label" $ do let program = map show $ execLazyboy $ do withLocalLabel $ \label -> do write (Address 0xC000) 0x97 program `shouldBe` [ ".L1:" , "ld HL, $C000" , "ld [HL], 151" ] describe "embedImage" $ do it "leverages RGBASM to include a binary" $ do let program = execLazyboy $ embedImage "test.bin" program `shouldBe` [JP $ Name $ Global 2, LABEL $ Global 1, INCLUDE "test.bin", LABEL $ Global 2] describe "embedBytes" $ do it "defines a raw sequence of bytes" $ do let program = execLazyboy $ embedBytes [0x00, 0x01, 0x02] program `shouldBe` [JP $ Name $ Global 2, LABEL $ Global 1, BYTES [0x00, 0x01, 0x02], LABEL $ Global 2] describe "Lazyboy.Target.ASM" $ do describe "show" $ do it "disallows loading [AF] into A" $ do disallow (show $ LDArr AF) it "disallows loading [SP] into A" $ do disallow (show $ LDArr SP) it "disallows loading [PC] into A" $ do disallow (show $ LDArr PC) it "disallows loading A into [AF]" $ do disallow (show $ LDrrA AF) it "disallows loading A into [SP]" $ do disallow (show $ LDrrA SP) it "disallows loading A into [PC]" $ do disallow (show $ LDrrA PC) it "disallows loading a 16 bit value into AF" $ do disallow $ show $ LDrrnn AF $ Address 0x00 it "disallows loading a 16 bit value into PC" $ do disallow $ show $ LDrrnn PC $ Address 0x00 it "disallows pushing stack pointer" $ do disallow (show $ PUSH SP) it "disallows pushing program counter" $ do disallow (show $ PUSH PC) it "disallows popping stack pointer" $ do disallow (show $ POP SP) it "disallows popping program counter" $ do disallow (show $ POP PC) it "disallows an invalid RST vector value" $ do disallow (show $ RST 0x02) it "disallows adding AF to HL" $ do disallow (show $ ADDHLrr AF) it "disallows adding PC to HL" $ do disallow (show $ ADDHLrr PC) it "disallows incrementing AF" $ do disallow (show $ INCrr AF) it "disallows incrementing PC" $ do disallow (show $ INCrr PC) it "disallows decrementing AF" $ do disallow (show $ DECrr AF) it "disallows decrementing PC" $ do disallow (show $ DECrr PC) it "enforces only 3-bit values can be passed to BIT instructions" $ do disallow (show $ BITnr 0x80 A) it "formats embedded byte sequences correctly" $ do let program = map show $ execLazyboy $ tell [BYTES [97, 98]] program `shouldBe` ["db $61,$62" ]