{-# LANGUAGE ForeignFunctionInterface, RankNTypes, FlexibleContexts, ExistentialQuantification #-} -- Test framework imports import Test.Framework (defaultMain, testGroup, Test) import Test.Framework.Providers.HUnit import Test.HUnit hiding (Test, Testable) import Test.Framework.Providers.QuickCheck2 import Test.QuickCheck -- Code to test import Data.Bits.Extras import Data.Word import Data.Int import Data.Bits tests :: [Test] tests = [ testGroup "Test Cases" [ testCase "trailingZeros" test_trailingZeros_all ] ] main :: IO () main = defaultMain tests -- TODO: Use Quickcheck to produce arbitrary values? testPattern :: Integral a => a testPattern = 0xdeadbeef type PolyTest = (ExtraBits a, Integral a, Bounded a) => a -> Assertion testTypes :: PolyTest -> Assertion testTypes t = do t (testPattern :: Int) t (testPattern :: Word) t (testPattern :: Int8) t (testPattern :: Int16) t (testPattern :: Int32) t (testPattern :: Int64) t (testPattern :: Word8) t (testPattern :: Word16) t (testPattern :: Word32) t (testPattern :: Word64) test_trailingZeros :: PolyTest test_trailingZeros i = do let t0 = i - i -- No test for 0, as the result would be undefined trailingZeros (t0 + 1) @?= fromIntegral t0 trailingZeros (t0 + 3) @?= fromIntegral t0 trailingZeros (t0 + 2) @?= fromIntegral t0 + 1 let hbitshift = bitSize i - 1 hbitset = (t0 + 1) `shiftL` hbitshift assertEqual "High bit set" (fromIntegral hbitset) hbitshift test_trailingZeros_all :: Assertion test_trailingZeros_all = testTypes test_trailingZeros