Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Page allocator tests #160

Merged
merged 23 commits into from
Oct 7, 2023
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
dea7229
Adding Page Allocator tests
kpadmasola Oct 1, 2023
95177d0
Refactor mallocator test some more
luc-tielen Sep 27, 2023
4dc9d98
Add setup code for btree unit tests
luc-tielen Sep 30, 2023
a278e0c
Add more btree tests
luc-tielen Oct 1, 2023
747b0a0
Add iterator test + function to convert btree to list
luc-tielen Oct 2, 2023
2d941c9
Add more btree tests
luc-tielen Oct 2, 2023
51023b7
Add depth and num node checks to basic btree test
luc-tielen Oct 3, 2023
b8d134b
Disallow xit in tests also
luc-tielen Oct 4, 2023
e0668e0
Fix potential uninitialized memory access in btree find
luc-tielen Oct 4, 2023
630fa0f
Add small fixes in btree unit tests
luc-tielen Oct 4, 2023
65c21af
Fix another potential memory access issue
luc-tielen Oct 4, 2023
0457bfb
Fix another potential memory access issue during insert
luc-tielen Oct 4, 2023
11227e8
Fix another potential memory access issue during bounds computation
luc-tielen Oct 4, 2023
0cc444e
Fix bug due to comparing signed values as unsigned
luc-tielen Oct 5, 2023
9969c2a
Clean up btree tests
luc-tielen Oct 5, 2023
ccd7eab
Fix CI check for tests marked with "xit"
luc-tielen Oct 5, 2023
f014a91
Rebasing on changes from main
kpadmasola Oct 1, 2023
85db518
Updated, still not working..
kpadmasola Oct 6, 2023
ac006f6
Merge branch 'main' of git.luolix.top-personal:placidex/eclair-lang into …
kpadmasola Oct 6, 2023
989a03a
added debug stmts, now code getting generated and compiled, but test …
kpadmasola Oct 7, 2023
170aca5
Fix setup code
luc-tielen Oct 7, 2023
3b3f193
Add test for roundToNearestPageSize
luc-tielen Oct 7, 2023
0cbb0e5
Remove focus from tests
luc-tielen Oct 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eclair-lang.cabal
Original file line number Diff line number Diff line change
@@ -257,6 +257,7 @@ test-suite eclair-test
Test.Eclair.ArgParserSpec
Test.Eclair.JSONSpec
Test.Eclair.LLVM.Allocator.MallocSpec
Test.Eclair.LLVM.Allocator.PageSpec
Test.Eclair.LLVM.Allocator.Utils
Test.Eclair.LLVM.BTreeSpec
Test.Eclair.LLVM.HashSpec
1 change: 1 addition & 0 deletions lib/Eclair/LLVM/Allocator/Page.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Eclair.LLVM.Allocator.Page
( Page
, allocator
, roundToNearestPageSize -- for testing only
) where

import Eclair.LLVM.Allocator.Common
6 changes: 4 additions & 2 deletions tests/eclair/Test/Eclair/LLVM/Allocator/MallocSpec.hs
Original file line number Diff line number Diff line change
@@ -59,8 +59,10 @@ cgExternals = do
pure $ Externals mallocFn freeFn notUsed notUsed notUsed notUsed notUsed

-- Helper test code for initializing and freeing a struct from native code:
cgTestCode :: Type -> Operand -> Operand -> ModuleBuilderT IO ()
cgTestCode ty mallocFn freeFn = do
cgTestCode :: Type -> Externals -> ModuleBuilderT IO ()
cgTestCode ty exts = do
let mallocFn = extMalloc exts
freeFn = extFree exts
_ <- function "mallocator_new" [] (ptr ty) $ \[] ->
ret =<< call mallocFn [int32 1]
_ <- function "mallocator_delete" [(ptr ty, "allocator")] void $ \[alloc] ->
120 changes: 120 additions & 0 deletions tests/eclair/Test/Eclair/LLVM/Allocator/PageSpec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{-# OPTIONS_GHC -Wno-deprecations -Wno-incomplete-uni-patterns #-}
module Test.Eclair.LLVM.Allocator.PageSpec
( module Test.Eclair.LLVM.Allocator.PageSpec
) where

import Prelude hiding (void)
import Control.Monad.Morph
import Eclair.LLVM.Allocator.Page
import Eclair.LLVM.Allocator.Common
import Test.Eclair.LLVM.Allocator.Utils
import Eclair.LLVM.Codegen hiding (retVoid)
import System.Directory.Extra
import System.Posix.DynamicLinker
import Test.Hspec
import Control.Exception (bracket)
import Foreign hiding (void)
import Foreign.LibFFI

data PageAllocator

spec :: Spec
spec = describe "PageAllocator" $
aroundAll (setupAndTeardown testDir) $ parallel $ do
it "can be initialized and destroyed" $ \bindings ->
withAlloc bindings $ \obj -> do
fnInit bindings obj
fnDestroy bindings obj

it "can allocate and free memory" $ \bindings -> do
let numBytes = 1
value = 42
withAlloc bindings $ \obj -> do
fnInit bindings obj
memory <- fnAlloc bindings obj numBytes
let memoryEnd = memory `plusPtr` 4095
poke memory value
poke memoryEnd value
value' <- peek memory
valueEnd <- peek memoryEnd
fnFree bindings obj memory numBytes
fnDestroy bindings obj
value' `shouldBe` value
valueEnd `shouldBe` value

it "rounds up to the nearest page size" $ \_ -> do
withNearestPageSize $ \roundFn -> do
result1 <- roundFn 1
result2 <- roundFn 4096
result3 <- roundFn 4097
result4 <- roundFn 0
result5 <- roundFn 12345678
result1 `shouldBe` 4096
result2 `shouldBe` 4096
result3 `shouldBe` (4096 * 2)
result4 `shouldBe` 0
result5 `shouldBe` 12349440

setupAndTeardown :: FilePath -> ActionWith (Bindings PageAllocator) -> IO ()
setupAndTeardown dir =
bracket (setup dir) teardown

setup :: FilePath -> IO (Bindings PageAllocator)
setup dir = do
createDirectoryIfMissing False dir
compileAllocatorCode allocator prefix cgExternals cgTestCode dir
loadNativeCode prefix dir

teardown :: Bindings PageAllocator -> IO ()
teardown =
dlclose . dynamicLib

cgExternals :: ModuleBuilderT IO Externals
cgExternals = do
-- Need malloc and free to allocate the allocator itself
mallocFn <- extern "malloc" [i32] (ptr i8)
freeFn <- extern "free" [ptr i8] void
-- mmap [hint, numBytes', prot, flags, noFd, offset]
mmapFn <- extern "mmap" [ptr void, i64, i32, i32, i32, i32] (ptr void)
-- munmap [memory, len']
munmapFn <- extern "munmap" [ptr void, i64] i32
pure $ Externals mallocFn freeFn notUsed notUsed notUsed mmapFn munmapFn

-- Helper test code for allocating and freeing a struct from native code:
cgTestCode :: Type -> Externals -> ModuleBuilderT IO ()
cgTestCode ty exts = do
let mallocFn = extMalloc exts
freeFn = extFree exts
_ <- function "pageallocator_new" [] (ptr ty) $ \[] ->
ret =<< call mallocFn [int32 1]
_ <- function "pageallocator_delete" [(ptr ty, "allocator")] void $ \[alloc] ->
call freeFn [alloc]
let roundToNearestInstructions numBytes =
hoist (hoist intoIO) $ hoist (`evalStateT` exts) $ roundToNearestPageSize numBytes
_ <- function "nearest_page_size" [(i32, "num_bytes")] i32 $ \[num] ->
ret =<< roundToNearestInstructions num
pass

withNearestPageSize :: ((Word32 -> IO Word32) -> IO ()) -> IO ()
withNearestPageSize f =
bracket open close (\(_, roundFn) -> f roundFn)
where
open = do
dl <- dlopen (soFile testDir) [RTLD_LAZY]
roundingFn <- dlsym dl "nearest_page_size"
let roundFn numBytes =
fromIntegral <$> callFFI roundingFn retCUInt [argCUInt $ fromIntegral numBytes]
pure (dl, roundFn)
close = dlclose . fst

prefix :: Text
prefix = "pageallocator"

testDir :: FilePath
testDir = "/tmp/eclair-pageallocator"

notUsed :: a
notUsed = panic "Not used"

intoIO :: Identity a -> IO a
intoIO = pure . runIdentity
6 changes: 4 additions & 2 deletions tests/eclair/Test/Eclair/LLVM/Allocator/Utils.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{-# OPTIONS_GHC -Wno-deprecations #-}
module Test.Eclair.LLVM.Allocator.Utils
( Bindings(..)
, compileAllocatorCode
, loadNativeCode
, soFile
) where

import System.Process.Extra
@@ -31,14 +33,14 @@ compileAllocatorCode
:: Allocator a
-> Text
-> ModuleBuilderT IO Externals
-> (Type -> Operand -> Operand -> ModuleBuilderT IO ())
-> (Type -> Externals -> ModuleBuilderT IO ())
-> FilePath -> IO ()
compileAllocatorCode allocator prefix cgExts cgHelperCode dir = do
llvmIR <- runModuleBuilderT $ do
exts <- cgExts
let cgBlueprint = flip evalStateT exts $ cgAlloc prefix allocator
blueprint <- hoist intoIO cgBlueprint
cgHelperCode (bpType blueprint) (extMalloc exts) (extFree exts)
cgHelperCode (bpType blueprint) exts
let llvmIRText = ppllvm llvmIR
writeFileText (llFile dir) llvmIRText
callProcess "clang" ["-fPIC", "-shared", "-O0", "-o", soFile dir, llFile dir]
Loading