packages feed

language-c-quote-0.7.2: tests/unit/Main.hs

{-# LANGUAGE CPP #-}
{-# LANGUAGE QuasiQuotes #-}

module Main where

import Test.Framework
import Test.Framework.Providers.HUnit
import Test.HUnit ((@=?))

import Data.Loc (SrcLoc, noLoc)
import Language.C.Quote.C
import qualified Language.C.Syntax as C
import System.Exit (exitFailure, exitSuccess)

#if !MIN_VERSION_template_haskell(2,7,0)
import qualified Data.Loc
import qualified Data.Symbol
import qualified Language.C.Syntax
#endif /* !MIN_VERSION_template_haskell(2,7,0) */

main :: IO ()
main = defaultMain tests

tests :: [Test]
tests = [exp_id, exp_int, exp_float, exp_char, exp_string,
         exp_exp, exp_func, exp_args, exp_decl, exp_sdecl,
         exp_enum, exp_edecl, exp_stm, exp_param, exp_ty,
         pat_args, exp_hexp,
         exp_init, exp_inits, exp_item]

exp_id :: Test
exp_id = testCase "exp id" $ [cexp|$id:f($id:x, $id:y)|] @=? [cexp|f(x, y)|]
  where
    f :: String
    f = "f"

    x :: SrcLoc -> C.Id
    x = C.Id "x"

    y :: C.Id
    y = C.Id "y" noLoc

exp_int :: Test
exp_int = testCase "exp int" $
    [cexp|$int:one + $uint:one + $lint:one + $ulint:one|]
      @=? [cexp|1 + 1U + 1L + 1UL|]
  where
    one = 1

exp_float :: Test
exp_float = testCase "exp float" $
    [cexp|$float:one + $double:one + $ldouble:one|]
      @=? [cexp|1.0F + 1.0 + 1.0L|]
  where
    one = 1

exp_char :: Test
exp_char = testCase "exp char" $ [cexp|$char:a|] @=?  [cexp|'a'|]
    where
      a = 'a'

exp_string :: Test
exp_string =
    testCase "exp string" $ [cexp|$string:hello|] @=?  [cexp|"Hello, world\n"|]
  where
    hello = "Hello, world\n"

exp_exp :: Test
exp_exp =
    testCase "exp expression" $ [cexp|$exp:e1 + $exp:e2|] @=?  [cexp|1 + 2|]
  where
    e1 = [cexp|1|]
    e2 = [cexp|2|]

exp_func :: Test
exp_func = testCase "exp function" $
    [cunit|$func:f|]
      @=? [cunit|int add(int x) { return x + 10; }|]
  where
    f = add 10
    add n = [cfun|int add(int x) { return x + $int:n; } |]

exp_args :: Test
exp_args = testCase "exp args" $
    [cstm|f($exp:e1, $args:args, $exp:e2);|]
      @=? [cstm|f(1, 1, 2, 2);|]
  where
    e1 = [cexp|1|]
    e2 = [cexp|2|]
    args = [e1, e2]

exp_decl :: Test
exp_decl = testCase "exp decl" $
    [cfun|int inc(int n) {
             $decl:d1;
             $decls:decls

             return n + 1;
          }|]
       @=? [cfun|int inc(int n) {
                     int i;
                     int j;
                     char c = 'c';

                     return n + 1;
                  }|]
  where
    d1 = [cdecl|int i;|]
    d2 = [cdecl|int j;|]
    d3 = [cdecl|char c = 'c';|]
    decls = [d2, d3]

exp_sdecl :: Test
exp_sdecl = testCase "exp sdecl" $
    [cty|struct foo { $sdecl:d1 $sdecls:decls }|]
      @=? [cty|struct foo { int i; int j; char c; }|]
  where
    d1 = [csdecl|int i;|]
    d2 = [csdecl|int j;|]
    d3 = [csdecl|char c;|]
    decls = [d2, d3]

exp_enum :: Test
exp_enum = testCase "exp enum" $
    [cty|enum foo { $enum:enum1, $enums:enums }|]
      @=? [cty|enum foo { A = 0, B, C = 2 }|]
  where
    enum1 = [cenum|A = 0|]
    enum2 = [cenum|B|]
    enum3 = [cenum|C = 2|]
    enums = [enum2, enum3]

exp_edecl :: Test
exp_edecl = testCase "exp edecl" $
    [cunit|$edecl:d1 $edecls:decls|]
      @=? [cunit|int i; int j; char c = 'c';|]
  where
    d1 = [cedecl|int i;|]
    d2 = [cedecl|int j;|]
    d3 = [cedecl|char c = 'c';|]
    decls = [d2, d3]

exp_stm :: Test
exp_stm = testCase "exp stm" $
    [cfun|int add(int x) { $stms:stms return x + 1; }|]
      @=? [cfun|int add(int x) { a = 1; b = 2; return x + 1; }|]
  where
    one = 1
    stm1 = [cstm|a = $int:one;|]
    stm2 = [cstm|b = 2;|]
    stms = [stm1, stm2]

exp_param :: Test
exp_param = testCase "exp param" $
    [cdecl|int f($param:ty1, $params:tys);|]
      @=? [cdecl|int f(char, int, float);|]
  where
    ty1 = [cparam|char|]
    ty2 = [cparam|int|]
    ty3 = [cparam|float|]
    tys = [ty2, ty3]

exp_ty :: Test
exp_ty = testCase "exp ty" $
    [cdecl|$ty:ty1 f(const $ty:ty2);|]
      @=? [cdecl|int f(const float);|]
  where
    ty1 = [cty|int|]
    ty2 = [cty|float|]

pat_args :: Test
pat_args =
    testCase"pat args" $ stms @=?  [[cexp|2|], [cexp|3|]]
  where
    stms = case [cstm|f(1, 2, 3);|] of
             [cstm|f(1, $args:es);|] -> es
             _ -> []

exp_hexp :: Test
exp_hexp =
    testCase "exp hexp" $ [cexp|$ulint:(13 - 2*5)|] @=? [cexp|3UL|]

exp_init :: Test
exp_init = testCase "initializer" $
    [cinit|{$init:initializer, .a = 10}|] @=? [cinit|{{.d = 1}, .a = 10}|]
  where
    initializer = [cinit|{.d = 1}|]

exp_inits :: Test
exp_inits = testCase "initializers" $
    [cinit|{$inits:([initializer1, initializer2])}|] @=? [cinit|{{.d = 1},{.a = 10}}|]
  where
    initializer1 = [cinit|{.d = 1}|]
    initializer2 = [cinit|{.a = 10}|]

exp_item :: Test
exp_item = testCase "exp item" $
    [cfun|int add(int x) { int y = 2; return x + y; }|]
      @=? [cfun|int add(int x) { $items:([item1, item2]) }|]
  where
    item1 = [citem|int y = 2;|]
    item2 = [citem|return x + y;|]