hic-0.0.0.1: test/Language/Cimple/Analysis/ArrayUsageAnalysisSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Language.Cimple.Analysis.ArrayUsageAnalysisSpec (spec) where
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Language.Cimple.Analysis.ArrayUsageAnalysis
import qualified Language.Cimple.Analysis.GlobalStructuralAnalysis as GSA
import Language.Cimple.Hic.InferenceSpec (mustParse)
import Test.Hspec
spec :: Spec
spec = describe "Language.Cimple.Analysis.ArrayUsageAnalysis" $ do
it "identifies homogeneous local arrays" $ do
prog <- mustParse ["void f() { int a[10]; int i = 0; a[i] = 1; }"]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (LocalArray "f" "a") (aurFlavors res) `shouldBe` Just FlavorHomogeneous
it "identifies heterogeneous local arrays" $ do
prog <- mustParse ["void f() { int a[10]; a[0] = 1; a[1] = 2; }"]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (LocalArray "f" "a") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous
it "identifies mixed access as mixed" $ do
prog <- mustParse ["void f() { int a[10]; int i = 0; a[0] = 1; a[i] = 2; }"]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (LocalArray "f" "a") (aurFlavors res) `shouldBe` Just FlavorMixed
it "tracks struct member arrays across functions" $ do
prog <- mustParse
[ "struct Registry { int h[10]; };"
, "void set(struct Registry *r, int i) { r->h[i] = 1; }"
, "void f(struct Registry *r) { r->h[0] = 2; }"
]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (MemberArray "Registry" "h") (aurFlavors res) `shouldBe` Just FlavorMixed
it "distinguishes between different struct members" $ do
prog <- mustParse
[ "struct My_Struct { int a[10]; int b[10]; };"
, "void f(struct My_Struct *s) { s->a[0] = 1; s->b[1] = 2; }"
]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (MemberArray "My_Struct" "a") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous
Map.lookup (MemberArray "My_Struct" "b") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous
it "handles hexadecimal indices" $ do
prog <- mustParse ["void f() { int a[10]; a[0x1] = 1; a[0x2] = 2; }"]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (LocalArray "f" "a") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous
Map.lookup (LocalArray "f" "a") (aurAccesses res) `shouldBe` Just (Set.fromList [Just 1, Just 2])
it "handles nested struct member arrays" $ do
prog <- mustParse
[ "struct Inner { int h[10]; };"
, "struct Outer { struct Inner in; };"
, "void f(struct Outer *s) { s->in.h[0] = 1; }"
]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
Map.lookup (MemberArray "Inner" "h") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous
it "handles arrays accessed via pointer to struct member" $ do
prog <- mustParse
[ "struct My_Struct { int h[10]; };"
, "void f(struct My_Struct *s) { int *p = s->h; p[0] = 1; }"
]
let ts = GSA.garTypeSystem $ GSA.runGlobalStructuralAnalysis prog
let res = runArrayUsageAnalysis ts prog
-- Currently we don't track pointers to arrays, so p[0] might be missed
-- or identified as LocalArray "f" "p".
Map.lookup (LocalArray "f" "p") (aurFlavors res) `shouldBe` Just FlavorHeterogeneous