packages feed

grisette-0.4.0.0: test/Grisette/Core/Data/Class/SEqTests.hs

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Grisette.Core.Data.Class.SEqTests (seqTests) where

import Control.Monad.Except (ExceptT (ExceptT))
import Control.Monad.Identity
  ( Identity (Identity),
    IdentityT (IdentityT),
  )
import Control.Monad.Trans.Maybe (MaybeT (MaybeT))
import qualified Control.Monad.Writer.Lazy as WriterLazy
import qualified Control.Monad.Writer.Strict as WriterStrict
import Data.Bifunctor (Bifunctor (bimap))
import qualified Data.ByteString as B
import Data.Foldable (traverse_)
import Data.Functor.Sum (Sum (InL, InR))
import Data.Int (Int16, Int32, Int64, Int8)
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.Stack (HasCallStack)
import Generics.Deriving (Default (Default), Generic)
import Grisette.Core.Data.Class.LogicalOp (LogicalOp (symNot, (.&&)))
import Grisette.Core.Data.Class.SEq (SEq ((./=), (.==)))
import Grisette.Core.Data.Class.Solvable (Solvable (con))
import Grisette.Core.Data.Class.TestValues (conBool, ssymBool)
import Grisette.IR.SymPrim.Data.Prim.PartialEval.Bool (pevalEqvTerm)
import Grisette.IR.SymPrim.Data.SymPrim (SymBool (SymBool))
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.HUnit (testCase)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.HUnit (Assertion, (@=?))
import Test.QuickCheck (ioProperty)

data A = A1 | A2 SymBool | A3 SymBool SymBool
  deriving (Generic, Show, Eq)
  deriving (SEq) via (Default A)

concreteSEqOkProp :: (HasCallStack, SEq a, Eq a) => (a, a) -> Assertion
concreteSEqOkProp (i, j) = do
  i .== j @=? con (i == j)
  i ./= j @=? con (i /= j)

seqTests :: Test
seqTests =
  testGroup
    "SEq"
    [ testGroup
        "SEq for common types"
        [ testGroup
            "SymBool"
            [ testCase "conBool" $ do
                let bools :: [Bool] = [True, False]
                traverse_
                  ( \(i, j) ->
                      conBool i
                        .== conBool j
                        @=? conBool (i == j)
                  )
                  [(x, y) | x <- bools, y <- bools],
              testCase "conBool True vs SymBool" $ do
                conBool True .== ssymBool "a" @=? ssymBool "a",
              testCase "conBool False vs SymBool" $ do
                conBool False .== ssymBool "a" @=? symNot (ssymBool "a"),
              testCase "SymBool vs conBool True" $ do
                ssymBool "a" .== conBool True @=? ssymBool "a",
              testCase "SymBool vs conBool False" $ do
                ssymBool "a" .== conBool False @=? symNot (ssymBool "a"),
              testCase "SymBool vs same SymBool" $ do
                ssymBool "a" .== ssymBool "a" @=? conBool True,
              testCase "SymBool vs different SymBool" $ do
                let SymBool terma = ssymBool "a"
                    SymBool termb = ssymBool "b"
                ssymBool "a"
                  .== ssymBool "b"
                  @=? SymBool (pevalEqvTerm terma termb)
            ],
          testProperty "Bool" (ioProperty . concreteSEqOkProp @Bool),
          testProperty "Integer" (ioProperty . concreteSEqOkProp @Integer),
          testProperty "Char" (ioProperty . concreteSEqOkProp @Char),
          testProperty "Int" (ioProperty . concreteSEqOkProp @Int),
          testProperty "Int8" (ioProperty . concreteSEqOkProp @Int8),
          testProperty "Int16" (ioProperty . concreteSEqOkProp @Int16),
          testProperty "Int32" (ioProperty . concreteSEqOkProp @Int32),
          testProperty "Int64" (ioProperty . concreteSEqOkProp @Int64),
          testProperty "Word" (ioProperty . concreteSEqOkProp @Word),
          testProperty "Word8" (ioProperty . concreteSEqOkProp @Word8),
          testProperty "Word16" (ioProperty . concreteSEqOkProp @Word16),
          testProperty "Word32" (ioProperty . concreteSEqOkProp @Word32),
          testProperty "Word64" (ioProperty . concreteSEqOkProp @Word64),
          testGroup
            "List"
            [ testProperty "[Integer]" $
                ioProperty . concreteSEqOkProp @[Integer],
              testGroup
                "[SymBool]"
                [ testCase "Same length 1" $
                    [ssymBool "a"]
                      .== [ssymBool "b"]
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase "Same length 2" $
                    [ssymBool "a", ssymBool "b"]
                      .== [ssymBool "c", ssymBool "d"]
                      @=? (ssymBool "a" .== ssymBool "c")
                        .&& (ssymBool "b" .== ssymBool "d"),
                  testCase "length 1 vs length 0" $
                    [ssymBool "a"] .== [] @=? conBool False,
                  testCase "length 1 vs length 2" $
                    [ssymBool "a"]
                      .== [ssymBool "c", ssymBool "d"]
                      @=? conBool False
                ]
            ],
          testGroup
            "Maybe"
            [ testProperty "Maybe Integer" $
                ioProperty . concreteSEqOkProp @(Maybe Integer),
              testGroup
                "Maybe SymBool"
                [ testCase "Nothing vs Nothing" $
                    (Nothing :: Maybe SymBool) .== Nothing @=? conBool True,
                  testCase "Just vs Nothing" $
                    Just (ssymBool "a") .== Nothing @=? conBool False,
                  testCase "Nothing vs Just" $
                    Nothing .== Just (ssymBool "a") @=? conBool False,
                  testCase "Just vs Just" $
                    Just (ssymBool "a")
                      .== Just (ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b"
                ]
            ],
          testGroup
            "Either"
            [ testProperty "Either" $
                ioProperty . concreteSEqOkProp @(Either Integer Integer),
              testGroup
                "Either SymBool SymBool"
                [ testCase "Left vs Left" $
                    (Left (ssymBool "a") :: Either SymBool SymBool)
                      .== Left (ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase "Right vs Left" $
                    (Right (ssymBool "a") :: Either SymBool SymBool)
                      .== Left (ssymBool "b")
                      @=? conBool False,
                  testCase "Left vs Right" $
                    (Left (ssymBool "a") :: Either SymBool SymBool)
                      .== Right (ssymBool "b")
                      @=? conBool False,
                  testCase "Right vs Right" $
                    (Right (ssymBool "a") :: Either SymBool SymBool)
                      .== Right (ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b"
                ]
            ],
          testGroup
            "MaybeT"
            [ testProperty "MaybeT" $
                ioProperty
                  . concreteSEqOkProp @(MaybeT Maybe Integer)
                  . bimap MaybeT MaybeT,
              testGroup
                "MaybeT Maybe SymBool"
                [ testCase "MaybeT Nothing vs MaybeT Nothing" $
                    (MaybeT Nothing :: MaybeT Maybe SymBool)
                      .== MaybeT Nothing
                      @=? conBool True,
                  testCase "MaybeT Nothing vs MaybeT (Just Nothing)" $
                    (MaybeT Nothing :: MaybeT Maybe SymBool)
                      .== MaybeT (Just Nothing)
                      @=? conBool False,
                  testCase "MaybeT Nothing vs MaybeT (Just (Just v))" $
                    (MaybeT Nothing :: MaybeT Maybe SymBool)
                      .== MaybeT (Just (Just (ssymBool "a")))
                      @=? conBool False,
                  testCase "MaybeT (Just Nothing) vs MaybeT Nothing" $
                    MaybeT (Just Nothing)
                      .== (MaybeT Nothing :: MaybeT Maybe SymBool)
                      @=? conBool False,
                  testCase "MaybeT (Just (Just v)) vs MaybeT Nothing" $
                    MaybeT (Just (Just (ssymBool "a")))
                      .== (MaybeT Nothing :: MaybeT Maybe SymBool)
                      @=? conBool False,
                  testCase "MaybeT (Just Nothing) vs MaybeT (Just Nothing)" $
                    MaybeT (Just Nothing)
                      .== (MaybeT (Just Nothing) :: MaybeT Maybe SymBool)
                      @=? conBool True,
                  testCase "MaybeT (Just (Just v)) vs MaybeT (Just Nothing)" $
                    MaybeT (Just (Just (ssymBool "a")))
                      .== (MaybeT (Just Nothing) :: MaybeT Maybe SymBool)
                      @=? conBool False,
                  testCase "MaybeT (Just Nothing) vs MaybeT (Just (Just v))" $
                    MaybeT (Just Nothing)
                      .== ( MaybeT (Just (Just (ssymBool "b"))) ::
                              MaybeT Maybe SymBool
                          )
                      @=? conBool False,
                  testCase "MaybeT (Just (Just v)) vs MaybeT (Just (Just v))" $
                    MaybeT (Just (Just (ssymBool "a")))
                      .== ( MaybeT (Just (Just (ssymBool "b"))) ::
                              MaybeT Maybe SymBool
                          )
                      @=? ssymBool "a"
                        .== ssymBool "b"
                ]
            ],
          testGroup
            "ExceptT"
            [ testProperty "ExceptT Integer Maybe Itneger" $
                ioProperty
                  . concreteSEqOkProp @(ExceptT Integer Maybe Integer)
                  . bimap ExceptT ExceptT,
              testGroup
                "ExceptT SymBool Maybe SymBool"
                [ testCase "ExceptT Nothing vs ExceptT Nothing" $
                    (ExceptT Nothing :: ExceptT SymBool Maybe SymBool)
                      .== ExceptT Nothing
                      @=? conBool True,
                  testCase "ExceptT Nothing vs ExceptT (Just (Left v))" $
                    (ExceptT Nothing :: ExceptT SymBool Maybe SymBool)
                      .== ExceptT (Just (Left (ssymBool "a")))
                      @=? conBool False,
                  testCase "ExceptT Nothing vs ExceptT (Just (Right v))" $
                    (ExceptT Nothing :: ExceptT SymBool Maybe SymBool)
                      .== ExceptT (Just (Right (ssymBool "a")))
                      @=? conBool False,
                  testCase "ExceptT (Just (Left v)) vs ExceptT Nothing" $
                    ExceptT (Just (Left (ssymBool "a")))
                      .== (ExceptT Nothing :: ExceptT SymBool Maybe SymBool)
                      @=? conBool False,
                  testCase "ExceptT (Just (Right v)) vs ExceptT Nothing" $
                    ExceptT (Just (Right (ssymBool "a")))
                      .== (ExceptT Nothing :: ExceptT SymBool Maybe SymBool)
                      @=? conBool False,
                  testCase
                    "ExceptT (Just (Left v)) vs ExceptT (Just (Left v))"
                    $ ExceptT (Just (Left (ssymBool "a")))
                      .== ( ExceptT (Just (Left (ssymBool "b"))) ::
                              ExceptT SymBool Maybe SymBool
                          )
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase
                    "ExceptT (Just (Right v)) vs ExceptT (Just (Left v))"
                    $ ExceptT (Just (Right (ssymBool "a")))
                      .== ( ExceptT (Just (Left (ssymBool "b"))) ::
                              ExceptT SymBool Maybe SymBool
                          )
                      @=? conBool False,
                  testCase
                    "ExceptT (Just (Left v)) vs ExceptT (Just (Right v))"
                    $ ExceptT (Just (Left (ssymBool "a")))
                      .== ( ExceptT (Just (Right (ssymBool "b"))) ::
                              ExceptT SymBool Maybe SymBool
                          )
                      @=? conBool False,
                  testCase
                    "ExceptT (Just (Right v)) vs ExceptT (Just (Right v))"
                    $ ExceptT (Just (Right (ssymBool "a")))
                      .== ( ExceptT (Just (Right (ssymBool "b"))) ::
                              ExceptT SymBool Maybe SymBool
                          )
                      @=? ssymBool "a"
                        .== ssymBool "b"
                ]
            ],
          testProperty "()" (ioProperty . concreteSEqOkProp @()),
          testGroup
            "(,)"
            [ testProperty "(Integer, Integer)" $
                ioProperty . concreteSEqOkProp @(Integer, Integer),
              testCase "(SymBool, SymBool)" $ do
                (ssymBool "a", ssymBool "c")
                  .== (ssymBool "b", ssymBool "d")
                  @=? ssymBool "a"
                    .== ssymBool "b"
                    .&& ssymBool "c"
                      .== ssymBool "d"
            ],
          testGroup
            "(,,)"
            [ testProperty "(Integer, Integer, Integer)" $
                ioProperty . concreteSEqOkProp @(Integer, Integer, Integer),
              testCase "(SymBool, SymBool, SymBool)" $
                (ssymBool "a", ssymBool "c", ssymBool "e")
                  .== (ssymBool "b", ssymBool "d", ssymBool "f")
                  @=? (ssymBool "a" .== ssymBool "b")
                    .&& ( (ssymBool "c" .== ssymBool "d")
                            .&& (ssymBool "e" .== ssymBool "f")
                        )
            ],
          testGroup
            "(,,,)"
            [ testProperty
                "(Integer, Integer, Integer, Integer)"
                $ ioProperty
                  . concreteSEqOkProp @(Integer, Integer, Integer, Integer),
              testCase "(SymBool, SymBool, SymBool, SymBool)" $ do
                (ssymBool "a", ssymBool "c", ssymBool "e", ssymBool "g")
                  .== (ssymBool "b", ssymBool "d", ssymBool "f", ssymBool "h")
                  @=? ( (ssymBool "a" .== ssymBool "b")
                          .&& (ssymBool "c" .== ssymBool "d")
                      )
                    .&& ( (ssymBool "e" .== ssymBool "f")
                            .&& (ssymBool "g" .== ssymBool "h")
                        )
            ],
          testGroup
            "(,,,,)"
            [ testProperty
                "(Integer, Integer, Integer, Integer, Integer)"
                $ ioProperty
                  . concreteSEqOkProp
                    @(Integer, Integer, Integer, Integer, Integer),
              testCase "(SymBool, SymBool, SymBool, SymBool, SymBool)" $ do
                ( ssymBool "a",
                  ssymBool "c",
                  ssymBool "e",
                  ssymBool "g",
                  ssymBool "i"
                  )
                  .== ( ssymBool "b",
                        ssymBool "d",
                        ssymBool "f",
                        ssymBool "h",
                        ssymBool "j"
                      )
                  @=? ( (ssymBool "a" .== ssymBool "b")
                          .&& (ssymBool "c" .== ssymBool "d")
                      )
                    .&& ( (ssymBool "e" .== ssymBool "f")
                            .&& ( (ssymBool "g" .== ssymBool "h")
                                    .&& (ssymBool "i" .== ssymBool "j")
                                )
                        )
            ],
          testGroup
            "(,,,,,)"
            [ testProperty
                "(Integer, Integer, Integer, Integer, Integer, Integer)"
                $ ioProperty
                  . concreteSEqOkProp
                    @( Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer
                     ),
              testCase
                "(SymBool, SymBool, SymBool, SymBool, SymBool, SymBool)"
                $ ( ssymBool "a",
                    ssymBool "c",
                    ssymBool "e",
                    ssymBool "g",
                    ssymBool "i",
                    ssymBool "k"
                  )
                  .== ( ssymBool "b",
                        ssymBool "d",
                        ssymBool "f",
                        ssymBool "h",
                        ssymBool "j",
                        ssymBool "l"
                      )
                  @=? ( (ssymBool "a" .== ssymBool "b")
                          .&& ( (ssymBool "c" .== ssymBool "d")
                                  .&& (ssymBool "e" .== ssymBool "f")
                              )
                      )
                    .&& ( (ssymBool "g" .== ssymBool "h")
                            .&& ( (ssymBool "i" .== ssymBool "j")
                                    .&& (ssymBool "k" .== ssymBool "l")
                                )
                        )
            ],
          testGroup
            "(,,,,,,)"
            [ testProperty
                "(Integer, Integer, Integer, Integer, Integer, Integer, Integer)"
                $ ioProperty
                  . concreteSEqOkProp
                    @( Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer
                     ),
              testCase
                "(SymBool, SymBool, SymBool, SymBool, SymBool, SymBool, SymBool)"
                $ do
                  ( ssymBool "a",
                    ssymBool "c",
                    ssymBool "e",
                    ssymBool "g",
                    ssymBool "i",
                    ssymBool "k",
                    ssymBool "m"
                    )
                    .== ( ssymBool "b",
                          ssymBool "d",
                          ssymBool "f",
                          ssymBool "h",
                          ssymBool "j",
                          ssymBool "l",
                          ssymBool "n"
                        )
                    @=? ( (ssymBool "a" .== ssymBool "b")
                            .&& ( (ssymBool "c" .== ssymBool "d")
                                    .&& (ssymBool "e" .== ssymBool "f")
                                )
                        )
                      .&& ( ( (ssymBool "g" .== ssymBool "h")
                                .&& (ssymBool "i" .== ssymBool "j")
                            )
                              .&& ( (ssymBool "k" .== ssymBool "l")
                                      .&& (ssymBool "m" .== ssymBool "n")
                                  )
                          )
            ],
          testGroup
            "(,,,,,,,)"
            [ testProperty
                "(Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer)"
                $ ioProperty
                  . concreteSEqOkProp
                    @( Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer,
                       Integer
                     ),
              testCase
                "(SymBool, SymBool, SymBool, SymBool, SymBool, SymBool, SymBool, SymBool)"
                $ ( ssymBool "a",
                    ssymBool "c",
                    ssymBool "e",
                    ssymBool "g",
                    ssymBool "i",
                    ssymBool "k",
                    ssymBool "m",
                    ssymBool "o"
                  )
                  .== ( ssymBool "b",
                        ssymBool "d",
                        ssymBool "f",
                        ssymBool "h",
                        ssymBool "j",
                        ssymBool "l",
                        ssymBool "n",
                        ssymBool "p"
                      )
                  @=? ( ( (ssymBool "a" .== ssymBool "b")
                            .&& (ssymBool "c" .== ssymBool "d")
                        )
                          .&& ( (ssymBool "e" .== ssymBool "f")
                                  .&& (ssymBool "g" .== ssymBool "h")
                              )
                      )
                    .&& ( ( (ssymBool "i" .== ssymBool "j")
                              .&& (ssymBool "k" .== ssymBool "l")
                          )
                            .&& ( (ssymBool "m" .== ssymBool "n")
                                    .&& (ssymBool "o" .== ssymBool "p")
                                )
                        )
            ],
          testCase "ByteString" $ do
            let bytestrings :: [B.ByteString] = ["", "a", "ab"]
            traverse_
              (\(i, j) -> i .== j @=? conBool (i == j))
              [(x, y) | x <- bytestrings, y <- bytestrings],
          testGroup
            "Sum"
            [ testProperty "Sum Maybe Maybe Integer" $
                ioProperty
                  . ( \v ->
                        let eitherToSum ::
                              Either (Maybe Integer) (Maybe Integer) ->
                              Sum Maybe Maybe Integer
                            eitherToSum (Left x) = InL x
                            eitherToSum (Right x) = InR x
                         in concreteSEqOkProp (bimap eitherToSum eitherToSum v)
                    ),
              testGroup
                "Sum Maybe Maybe SymBool"
                [ testCase "InL (Just v) vs InL (Just v)" $
                    (InL $ Just $ ssymBool "a" :: Sum Maybe Maybe SymBool)
                      .== InL (Just $ ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase "InL (Just v) vs InR (Just v)" $
                    (InL $ Just $ ssymBool "a" :: Sum Maybe Maybe SymBool)
                      .== InR (Just $ ssymBool "b")
                      @=? conBool False,
                  testCase "InR (Just v) vs InR (Just v)" $
                    (InR $ Just $ ssymBool "a" :: Sum Maybe Maybe SymBool)
                      .== InR (Just $ ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase "InR (Just v) vs InL (Just v)" $
                    (InR $ Just $ ssymBool "a" :: Sum Maybe Maybe SymBool)
                      .== InL (Just $ ssymBool "b")
                      @=? conBool False
                ]
            ],
          testGroup
            "Writer"
            [ testGroup
                "Lazy"
                [ testProperty
                    "WriterT Integer (Either Integer) Integer"
                    ( ioProperty
                        . \( v1 :: Either Integer (Integer, Integer),
                             v2 :: Either Integer (Integer, Integer)
                             ) ->
                            concreteSEqOkProp
                              ( WriterLazy.WriterT v1,
                                WriterLazy.WriterT v2
                              )
                    ),
                  testGroup
                    "WriterT SymBool (Either SymBool) SymBool"
                    [ testCase "WriterT (Left v) vs WriterT (Left v)" $
                        ( WriterLazy.WriterT (Left $ ssymBool "a") ::
                            WriterLazy.WriterT SymBool (Either SymBool) SymBool
                        )
                          .== WriterLazy.WriterT (Left $ ssymBool "b")
                          @=? ssymBool "a"
                            .== ssymBool "b",
                      testCase "WriterT (Left v) vs WriterT (Right v)" $
                        ( WriterLazy.WriterT (Left $ ssymBool "a") ::
                            WriterLazy.WriterT SymBool (Either SymBool) SymBool
                        )
                          .== WriterLazy.WriterT
                            (Right (ssymBool "b", ssymBool "c"))
                          @=? conBool False,
                      testCase "WriterT (Right v) vs WriterT (Left v)" $
                        ( WriterLazy.WriterT
                            (Right (ssymBool "b", ssymBool "c")) ::
                            WriterLazy.WriterT SymBool (Either SymBool) SymBool
                        )
                          .== WriterLazy.WriterT (Left $ ssymBool "a")
                          @=? conBool False,
                      testCase "WriterT (Right v) vs WriterT (Right v)" $
                        ( WriterLazy.WriterT
                            (Right (ssymBool "a", ssymBool "b")) ::
                            WriterLazy.WriterT SymBool (Either SymBool) SymBool
                        )
                          .== WriterLazy.WriterT
                            (Right (ssymBool "c", ssymBool "d"))
                          @=? (ssymBool "a" .== ssymBool "c")
                            .&& (ssymBool "b" .== ssymBool "d")
                    ]
                ],
              testGroup
                "Strict"
                [ testProperty
                    "WriterT Integer (Either Integer) Integer"
                    ( ioProperty
                        . \( v1 :: Either Integer (Integer, Integer),
                             v2 :: Either Integer (Integer, Integer)
                             ) ->
                            concreteSEqOkProp
                              ( WriterStrict.WriterT v1,
                                WriterStrict.WriterT v2
                              )
                    ),
                  testGroup
                    "WriterT SymBool (Either SymBool) SymBool"
                    [ testCase "WriterT (Left v) vs WriterT (Left v)" $
                        ( WriterStrict.WriterT (Left $ ssymBool "a") ::
                            WriterStrict.WriterT
                              SymBool
                              (Either SymBool)
                              SymBool
                        )
                          .== WriterStrict.WriterT (Left $ ssymBool "b")
                          @=? ssymBool "a"
                            .== ssymBool "b",
                      testCase "WriterT (Left v) vs WriterT (Right v)" $
                        ( WriterStrict.WriterT (Left $ ssymBool "a") ::
                            WriterStrict.WriterT
                              SymBool
                              (Either SymBool)
                              SymBool
                        )
                          .== WriterStrict.WriterT
                            (Right (ssymBool "b", ssymBool "c"))
                          @=? conBool False,
                      testCase "WriterT (Right v) vs WriterT (Left v)" $
                        ( WriterStrict.WriterT
                            (Right (ssymBool "b", ssymBool "c")) ::
                            WriterStrict.WriterT
                              SymBool
                              (Either SymBool)
                              SymBool
                        )
                          .== WriterStrict.WriterT (Left $ ssymBool "a")
                          @=? conBool False,
                      testCase "WriterT (Right v) vs WriterT (Right v)" $
                        ( WriterStrict.WriterT
                            (Right (ssymBool "a", ssymBool "b")) ::
                            WriterStrict.WriterT
                              SymBool
                              (Either SymBool)
                              SymBool
                        )
                          .== WriterStrict.WriterT
                            (Right (ssymBool "c", ssymBool "d"))
                          @=? ssymBool "a"
                            .== ssymBool "c"
                            .&& ssymBool "b"
                              .== ssymBool "d"
                    ]
                ]
            ],
          testGroup
            "Identity"
            [ testProperty
                "Identity Integer"
                ( ioProperty . \(v1 :: Integer, v2) ->
                    concreteSEqOkProp (Identity v1, Identity v2)
                ),
              testCase "Identity SymBool" $ do
                (Identity $ ssymBool "a" :: Identity SymBool)
                  .== Identity (ssymBool "b")
                  @=? ssymBool "a"
                    .== ssymBool "b"
            ],
          testGroup
            "IdentityT"
            [ testProperty
                "IdentityT (Either Integer) Integer"
                ( ioProperty . \(v1 :: Either Integer Integer, v2) ->
                    concreteSEqOkProp (IdentityT v1, IdentityT v2)
                ),
              testGroup
                "IdentityT (Either SymBool) SymBool"
                [ testCase "IdentityT (Left v) vs IdentityT (Left v)" $
                    ( IdentityT $ Left $ ssymBool "a" ::
                        IdentityT (Either SymBool) SymBool
                    )
                      .== IdentityT (Left $ ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b",
                  testCase "IdentityT (Left v) vs IdentityT (Right v)" $
                    ( IdentityT $ Left $ ssymBool "a" ::
                        IdentityT (Either SymBool) SymBool
                    )
                      .== IdentityT (Right $ ssymBool "b")
                      @=? conBool False,
                  testCase "IdentityT (Right v) vs IdentityT (Left v)" $
                    ( IdentityT $ Right $ ssymBool "a" ::
                        IdentityT (Either SymBool) SymBool
                    )
                      .== IdentityT (Left $ ssymBool "b")
                      @=? conBool False,
                  testCase "IdentityT (Right v) vs IdentityT (Right v)" $
                    ( IdentityT $ Right $ ssymBool "a" ::
                        IdentityT (Either SymBool) SymBool
                    )
                      .== IdentityT (Right $ ssymBool "b")
                      @=? ssymBool "a"
                        .== ssymBool "b"
                ]
            ]
        ],
      testGroup
        "deriving SEq for ADT"
        [ testGroup
            "Simple ADT"
            [ testCase "A1 vs A1" $
                A1 .== A1 @=? conBool True,
              testCase "A1 vs A2" $
                A1 .== A2 (ssymBool "a") @=? conBool False,
              testCase "A1 vs A3" $
                A1 .== A3 (ssymBool "a") (ssymBool "b") @=? conBool False,
              testCase "A2 vs A1" $
                A2 (ssymBool "a") .== A1 @=? conBool False,
              testCase "A2 vs A2" $
                A2 (ssymBool "a")
                  .== A2 (ssymBool "b")
                  @=? ssymBool "a"
                    .== ssymBool "b",
              testCase "A2 vs A3" $
                A2 (ssymBool "a")
                  .== A3 (ssymBool "b") (ssymBool "c")
                  @=? conBool False,
              testCase "A3 vs A1" $
                A3 (ssymBool "a") (ssymBool "b") .== A1 @=? conBool False,
              testCase "A3 vs A2" $
                A3 (ssymBool "a") (ssymBool "b")
                  .== A2 (ssymBool "c")
                  @=? conBool False,
              testCase "A3 vs A3" $
                A3 (ssymBool "a") (ssymBool "b")
                  .== A3 (ssymBool "c") (ssymBool "d")
                  @=? (ssymBool "a" .== ssymBool "c")
                    .&& (ssymBool "b" .== ssymBool "d")
            ]
        ]
    ]