1-- 2-- Licensed to the Apache Software Foundation (ASF) under one 3-- or more contributor license agreements. See the NOTICE file 4-- distributed with this work for additional information 5-- regarding copyright ownership. The ASF licenses this file 6-- to you under the Apache License, Version 2.0 (the 7-- "License"); you may not use this file except in compliance 8-- with the License. You may obtain a copy of the License at 9-- 10-- http://www.apache.org/licenses/LICENSE-2.0 11-- 12-- Unless required by applicable law or agreed to in writing, 13-- software distributed under the License is distributed on an 14-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15-- KIND, either express or implied. See the License for the 16-- specific language governing permissions and limitations 17-- under the License. 18-- 19 20module JSONSpec where 21 22import Test.Hspec 23import Test.Hspec.QuickCheck (prop) 24 25import qualified Data.ByteString.Lazy as LBS 26import qualified Data.ByteString.Lazy.Char8 as C 27 28import Thrift.Types 29import Thrift.Transport 30import Thrift.Transport.Memory 31import Thrift.Protocol 32import Thrift.Protocol.JSON 33 34tString :: [Char] -> ThriftVal 35tString = TString . C.pack 36 37spec :: Spec 38spec = do 39 describe "JSONProtocol" $ do 40 describe "bool" $ do 41 it "writes true as 1" $ do 42 let val = True 43 trans <- openMemoryBuffer 44 let proto = JSONProtocol trans 45 writeVal proto (TBool val) 46 bin <-tRead trans 100 47 (C.unpack bin) `shouldBe` ['1'] 48 49 it "writes false as 0" $ do 50 let val = False 51 trans <- openMemoryBuffer 52 let proto = JSONProtocol trans 53 writeVal proto (TBool val) 54 bin <- tRead trans 100 55 (C.unpack bin) `shouldBe` ['0'] 56 57 prop "round trip" $ \val -> do 58 trans <- openMemoryBuffer 59 let proto = JSONProtocol trans 60 writeVal proto $ TBool val 61 val2 <- readVal proto T_BOOL 62 val2 `shouldBe` (TBool val) 63 64 describe "string" $ do 65 it "writes" $ do 66 trans <- openMemoryBuffer 67 let proto = JSONProtocol trans 68 writeVal proto (TString $ C.pack "\"a") 69 bin <- tRead trans 100 70 (C.unpack bin) `shouldBe` "\"\\\"a\"" 71 72 it "reads" $ do 73 trans <- openMemoryBuffer 74 let proto = JSONProtocol trans 75 tWrite trans $ C.pack "\"\\\"a\"" 76 val <- readVal proto (T_STRING) 77 val `shouldBe` (TString $ C.pack "\"a") 78 79 prop "round trip" $ \val -> do 80 trans <- openMemoryBuffer 81 let proto = JSONProtocol trans 82 writeVal proto (TString $ C.pack val) 83 val2 <- readVal proto (T_STRING) 84 val2 `shouldBe` (TString $ C.pack val) 85 86 describe "binary" $ do 87 it "writes with padding" $ do 88 trans <- openMemoryBuffer 89 let proto = JSONProtocol trans 90 writeVal proto (TBinary $ LBS.pack [1]) 91 bin <- tRead trans 100 92 (C.unpack bin) `shouldBe` "\"AQ==\"" 93 94 it "reads with padding" $ do 95 trans <- openMemoryBuffer 96 let proto = JSONProtocol trans 97 tWrite trans $ C.pack "\"AQ==\"" 98 val <- readVal proto (T_BINARY) 99 val `shouldBe` (TBinary $ LBS.pack [1]) 100 101 it "reads without padding" $ do 102 trans <- openMemoryBuffer 103 let proto = JSONProtocol trans 104 tWrite trans $ C.pack "\"AQ\"" 105 val <- readVal proto (T_BINARY) 106 val `shouldBe` (TBinary $ LBS.pack [1]) 107 108 prop "round trip" $ \val -> do 109 trans <- openMemoryBuffer 110 let proto = JSONProtocol trans 111 writeVal proto (TBinary $ LBS.pack val) 112 val2 <- readVal proto (T_BINARY) 113 val2 `shouldBe` (TBinary $ LBS.pack val) 114 115 describe "list" $ do 116 it "writes empty list" $ do 117 trans <- openMemoryBuffer 118 let proto = JSONProtocol trans 119 writeVal proto (TList T_BYTE []) 120 bin <- tRead trans 100 121 (C.unpack bin) `shouldBe` "[\"i8\",0]" 122 123 it "reads empty" $ do 124 trans <- openMemoryBuffer 125 let proto = JSONProtocol trans 126 tWrite trans (C.pack "[\"i8\",0]") 127 val <- readVal proto (T_LIST T_BYTE) 128 val `shouldBe` (TList T_BYTE []) 129 130 it "writes single element" $ do 131 trans <- openMemoryBuffer 132 let proto = JSONProtocol trans 133 writeVal proto (TList T_BYTE [TByte 0]) 134 bin <- tRead trans 100 135 (C.unpack bin) `shouldBe` "[\"i8\",1,0]" 136 137 it "reads single element" $ do 138 trans <- openMemoryBuffer 139 let proto = JSONProtocol trans 140 tWrite trans (C.pack "[\"i8\",1,0]") 141 val <- readVal proto (T_LIST T_BYTE) 142 val `shouldBe` (TList T_BYTE [TByte 0]) 143 144 it "reads elements" $ do 145 trans <- openMemoryBuffer 146 let proto = JSONProtocol trans 147 tWrite trans (C.pack "[\"i8\",2,42, 43]") 148 val <- readVal proto (T_LIST T_BYTE) 149 val `shouldBe` (TList T_BYTE [TByte 42, TByte 43]) 150 151 prop "round trip" $ \val -> do 152 trans <- openMemoryBuffer 153 let proto = JSONProtocol trans 154 writeVal proto $ (TList T_STRING $ map tString val) 155 val2 <- readVal proto $ T_LIST T_STRING 156 val2 `shouldBe` (TList T_STRING $ map tString val) 157 158 describe "set" $ do 159 it "writes empty" $ do 160 trans <- openMemoryBuffer 161 let proto = JSONProtocol trans 162 writeVal proto (TSet T_BYTE []) 163 bin <- tRead trans 100 164 (C.unpack bin) `shouldBe` "[\"i8\",0]" 165 166 it "reads empty" $ do 167 trans <- openMemoryBuffer 168 let proto = JSONProtocol trans 169 tWrite trans (C.pack "[\"i8\",0]") 170 val <- readVal proto (T_SET T_BYTE) 171 val `shouldBe` (TSet T_BYTE []) 172 173 it "reads single element" $ do 174 trans <- openMemoryBuffer 175 let proto = JSONProtocol trans 176 tWrite trans (C.pack "[\"i8\",1,0]") 177 val <- readVal proto (T_SET T_BYTE) 178 val `shouldBe` (TSet T_BYTE [TByte 0]) 179 180 it "reads elements" $ do 181 trans <- openMemoryBuffer 182 let proto = JSONProtocol trans 183 tWrite trans (C.pack "[\"i8\",2,42, 43]") 184 val <- readVal proto (T_SET T_BYTE) 185 val `shouldBe` (TSet T_BYTE [TByte 42, TByte 43]) 186 187 prop "round trip" $ \val -> do 188 trans <- openMemoryBuffer 189 let proto = JSONProtocol trans 190 writeVal proto $ (TSet T_STRING $ map tString val) 191 val2 <- readVal proto $ T_SET T_STRING 192 val2 `shouldBe` (TSet T_STRING $ map tString val) 193 194 describe "map" $ do 195 it "writes empty" $ do 196 trans <- openMemoryBuffer 197 let proto = JSONProtocol trans 198 writeVal proto (TMap T_BYTE T_BYTE []) 199 bin <- tRead trans 100 200 (C.unpack bin) `shouldBe`"[\"i8\",\"i8\",0,{}]" 201 202 it "reads empty" $ do 203 trans <- openMemoryBuffer 204 let proto = JSONProtocol trans 205 tWrite trans (C.pack "[\"i8\",\"i8\",0,{}]") 206 val <- readVal proto (T_MAP T_BYTE T_BYTE) 207 val `shouldBe` (TMap T_BYTE T_BYTE []) 208 209 it "reads string-string" $ do 210 let bin = "[\"str\",\"str\",2,{\"a\":\"2\",\"b\":\"blah\"}]" 211 trans <- openMemoryBuffer 212 let proto = JSONProtocol trans 213 tWrite trans (C.pack bin) 214 val <- readVal proto (T_MAP T_STRING T_STRING) 215 val`shouldBe` (TMap T_STRING T_STRING [(tString "a", tString "2"), (tString "b", tString "blah")]) 216 217 prop "round trip" $ \val -> do 218 trans <- openMemoryBuffer 219 let proto = JSONProtocol trans 220 writeVal proto $ (TMap T_STRING T_STRING $ map toKV val) 221 val2 <- readVal proto $ T_MAP T_STRING T_STRING 222 val2 `shouldBe` (TMap T_STRING T_STRING $ map toKV val) 223 where 224 toKV v = (tString v, tString v) 225 226