packages feed

willow-0.1.0.0: test/Test/Willow/Property/Encoding/GB.hs

{-|
Description:    

Copyright:      (c) 2020 Samuel May
License:        MPL-2.0
Maintainer:     ag.eitilt@gmail.com

Stability:      experimental
Portability:    portable
-}
module Test.Willow.Property.Encoding.GB
    ( tests
    ) where


import qualified Hedgehog as H
import qualified Hedgehog.Gen as H.G
import qualified Hedgehog.Range as H.R

import Web.Willow.Common.Encoding

import Test.Willow.Property.Common


tests :: H.Group
tests = packGroup "Web.Willow.Common.Encoding.GB"
    -- Single byte tests handled in "unit" due to limited number
    [ decodeEndOfStream
    , decodeTwoByteInvalid
    , decodeThreeByteInvalid
    , decodeFourByteInvalid
    , decodeOneByteLookup
    , decodeTwoByteLookup
    , decodeFourByteLookup
    ]


decodeEndOfStream :: Test
decodeEndOfStream = packTest "incomplete character" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    second <- H.forAll . H.G.word8 $ H.R.linear 0x30 0x39
    third <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    checkEndOfStream enc [first, second, third]


decodeTwoByteInvalid :: Test
decodeTwoByteInvalid = packTest "invalid second byte" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    second <- H.forAll $ H.G.choice
        [ H.G.word8 $ H.R.linear 0x00 0x2F
        , H.G.word8 $ H.R.linear 0x3A 0xFE
        , H.G.constant 0xFF
        ]
    let check = if second <= 0x7F
            then checkInvalid
            else checkInvalidAll
    check enc [first, second]

decodeThreeByteInvalid :: Test
decodeThreeByteInvalid = packTest "invalid third byte" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    second <- H.forAll . H.G.word8 $ H.R.linear 0x30 0x39
    third <- H.forAll $ H.G.choice
        [ H.G.word8 $ H.R.linear 0x00 0x80
        , H.G.constant 0xFF
        ]
    checkInvalid enc [first, second, third]

decodeFourByteInvalid :: Test
decodeFourByteInvalid = packTest "invalid fourth byte" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    second <- H.forAll . H.G.word8 $ H.R.linear 0x30 0x39
    third <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    fourth <- H.forAll $ H.G.choice
        [ H.G.word8 $ H.R.linear 0x00 0x2F
        , H.G.word8 $ H.R.linear 0x3A 0xFE
        , H.G.constant 0xFF
        ]
    checkInvalid enc [first, second, third, fourth]


decodeOneByteLookup :: Test
decodeOneByteLookup = packTest "one-byte sequence" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll $ H.G.choice
        [ H.G.word8 $ H.R.linear 0x00 0x80
        , H.G.constant 0xFF
        ]
    checkTrailing enc [first]

decodeTwoByteLookup :: Test
decodeTwoByteLookup = packTest "two-byte sequence" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    first <- H.forAll . H.G.word8 $ H.R.linear 0x81 0xFE
    second <- H.forAll . H.G.choice $ map H.G.word8
        [ H.R.linear 0x40 0x7E
        , H.R.linear 0x80 0xFE
        ]
    if second <= 0x7F
        then checkTrailing enc [first, second]
        else checkTrailingAll enc [first, second]

decodeFourByteLookup :: Test
decodeFourByteLookup = packTest "four-byte sequence" $ do
    enc <- H.forAll $ H.G.element [Gbk, Gb18030]
    (first, second, third, fourth) <- H.forAll $ H.G.choice
        [ do
            b1 <- H.G.word8 $ H.R.linear 0x81 0xFE
            b2 <- H.G.word8 $ H.R.linear 0x30 0x39
            b3 <- H.G.word8 $ H.R.linear 0x81 0xFE
            b4 <- H.G.word8 $ H.R.linear 0x30 0x39
            return (b1, b2, b3, b4)
        , do    -- null range between 39419 and 189000
            b1 <- H.G.word8 $ H.R.linear 0x84 0xE9
            let (l2, h2) = case b1 of
                    0x84 -> (0x31, 0x39)
                    _ -> (0x30, 0x39)
            b2 <- H.G.word8 $ H.R.linear l2 h2
            let l3 = case (b1, b2) of
                    (0x84, 0x31) -> 0xA4
                    _ -> 0x81
            b3 <- H.G.word8 $ H.R.linear l3 0xFE
            let (l4, h4) = case (b1, b2, b3) of
                    (0x84, 0x31, 0xA4) -> (0x39, 0x39)
                    (0xE9, 0x39, 0xFE) -> (0x30, 0x38)
                    _ -> (0x30, 0x39)
            b4 <- H.G.word8 $ H.R.linear l4 h4
            return (b1, b2, b3, b4)
        , do    -- null range above 1237575
            b1 <- H.G.word8 $ H.R.linear 0xE3 0xFE
            let l2 = case b1 of
                    0xE3 -> 0x32
                    _ -> 0x30
            b2 <- H.G.word8 $ H.R.linear l2 0x39
            let l3 = case (b1, b2) of
                    (0xE3, 0x32) -> 0x9A
                    _ -> 0x81
            b3 <- H.G.word8 $ H.R.linear l3 0xFE
            let l4 = case (b1, b2, b3) of
                    (0xE3, 0x32, 0x9A) -> 0x36
                    _ -> 0x30
            b4 <- H.G.word8 $ H.R.linear l4 0x39
            return (b1, b2, b3, b4)
        ]
    checkTrailingAll enc [first, second, third, fourth]