1# encoding: UTF-8 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20 21require 'spec_helper' 22 23describe 'JsonProtocol' do 24 25 describe Thrift::JsonProtocol do 26 before(:each) do 27 @trans = Thrift::MemoryBufferTransport.new 28 @prot = Thrift::JsonProtocol.new(@trans) 29 end 30 31 it "should write json escaped char" do 32 @prot.write_json_escape_char("\n") 33 expect(@trans.read(@trans.available)).to eq('\u000a') 34 35 @prot.write_json_escape_char(" ") 36 expect(@trans.read(@trans.available)).to eq('\u0020') 37 end 38 39 it "should write json char" do 40 @prot.write_json_char("\n") 41 expect(@trans.read(@trans.available)).to eq('\\n') 42 43 @prot.write_json_char(" ") 44 expect(@trans.read(@trans.available)).to eq(' ') 45 46 @prot.write_json_char("\\") 47 expect(@trans.read(@trans.available)).to eq("\\\\") 48 49 @prot.write_json_char("@") 50 expect(@trans.read(@trans.available)).to eq('@') 51 end 52 53 it "should write json string" do 54 @prot.write_json_string("this is a \\ json\nstring") 55 expect(@trans.read(@trans.available)).to eq("\"this is a \\\\ json\\nstring\"") 56 end 57 58 it "should write json base64" do 59 @prot.write_json_base64("this is a base64 string") 60 expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"") 61 end 62 63 it "should write json integer" do 64 @prot.write_json_integer(45) 65 expect(@trans.read(@trans.available)).to eq("45") 66 67 @prot.write_json_integer(33000) 68 expect(@trans.read(@trans.available)).to eq("33000") 69 70 @prot.write_json_integer(3000000000) 71 expect(@trans.read(@trans.available)).to eq("3000000000") 72 73 @prot.write_json_integer(6000000000) 74 expect(@trans.read(@trans.available)).to eq("6000000000") 75 end 76 77 it "should write json double" do 78 @prot.write_json_double(12.3) 79 expect(@trans.read(@trans.available)).to eq("12.3") 80 81 @prot.write_json_double(-3.21) 82 expect(@trans.read(@trans.available)).to eq("-3.21") 83 84 @prot.write_json_double(((+1.0/0.0)/(+1.0/0.0))) 85 expect(@trans.read(@trans.available)).to eq("\"NaN\"") 86 87 @prot.write_json_double((+1.0/0.0)) 88 expect(@trans.read(@trans.available)).to eq("\"Infinity\"") 89 90 @prot.write_json_double((-1.0/0.0)) 91 expect(@trans.read(@trans.available)).to eq("\"-Infinity\"") 92 end 93 94 it "should write json object start" do 95 @prot.write_json_object_start 96 expect(@trans.read(@trans.available)).to eq("{") 97 end 98 99 it "should write json object end" do 100 @prot.write_json_object_end 101 expect(@trans.read(@trans.available)).to eq("}") 102 end 103 104 it "should write json array start" do 105 @prot.write_json_array_start 106 expect(@trans.read(@trans.available)).to eq("[") 107 end 108 109 it "should write json array end" do 110 @prot.write_json_array_end 111 expect(@trans.read(@trans.available)).to eq("]") 112 end 113 114 it "should write message begin" do 115 @prot.write_message_begin("name", 12, 32) 116 expect(@trans.read(@trans.available)).to eq("[1,\"name\",12,32") 117 end 118 119 it "should write message end" do 120 @prot.write_message_end 121 expect(@trans.read(@trans.available)).to eq("]") 122 end 123 124 it "should write struct begin" do 125 @prot.write_struct_begin("name") 126 expect(@trans.read(@trans.available)).to eq("{") 127 end 128 129 it "should write struct end" do 130 @prot.write_struct_end 131 expect(@trans.read(@trans.available)).to eq("}") 132 end 133 134 it "should write field begin" do 135 @prot.write_field_begin("name", Thrift::Types::STRUCT, 32) 136 expect(@trans.read(@trans.available)).to eq("32{\"rec\"") 137 end 138 139 it "should write field end" do 140 @prot.write_field_end 141 expect(@trans.read(@trans.available)).to eq("}") 142 end 143 144 it "should write field stop" do 145 @prot.write_field_stop 146 expect(@trans.read(@trans.available)).to eq("") 147 end 148 149 it "should write map begin" do 150 @prot.write_map_begin(Thrift::Types::STRUCT, Thrift::Types::LIST, 32) 151 expect(@trans.read(@trans.available)).to eq("[\"rec\",\"lst\",32,{") 152 end 153 154 it "should write map end" do 155 @prot.write_map_end 156 expect(@trans.read(@trans.available)).to eq("}]") 157 end 158 159 it "should write list begin" do 160 @prot.write_list_begin(Thrift::Types::STRUCT, 32) 161 expect(@trans.read(@trans.available)).to eq("[\"rec\",32") 162 end 163 164 it "should write list end" do 165 @prot.write_list_end 166 expect(@trans.read(@trans.available)).to eq("]") 167 end 168 169 it "should write set begin" do 170 @prot.write_set_begin(Thrift::Types::STRUCT, 32) 171 expect(@trans.read(@trans.available)).to eq("[\"rec\",32") 172 end 173 174 it "should write set end" do 175 @prot.write_set_end 176 expect(@trans.read(@trans.available)).to eq("]") 177 end 178 179 it "should write bool" do 180 @prot.write_bool(true) 181 expect(@trans.read(@trans.available)).to eq("1") 182 183 @prot.write_bool(false) 184 expect(@trans.read(@trans.available)).to eq("0") 185 end 186 187 it "should write byte" do 188 @prot.write_byte(100) 189 expect(@trans.read(@trans.available)).to eq("100") 190 end 191 192 it "should write i16" do 193 @prot.write_i16(1000) 194 expect(@trans.read(@trans.available)).to eq("1000") 195 end 196 197 it "should write i32" do 198 @prot.write_i32(3000000000) 199 expect(@trans.read(@trans.available)).to eq("3000000000") 200 end 201 202 it "should write i64" do 203 @prot.write_i64(6000000000) 204 expect(@trans.read(@trans.available)).to eq("6000000000") 205 end 206 207 it "should write double" do 208 @prot.write_double(1.23) 209 expect(@trans.read(@trans.available)).to eq("1.23") 210 211 @prot.write_double(-32.1) 212 expect(@trans.read(@trans.available)).to eq("-32.1") 213 214 @prot.write_double(((+1.0/0.0)/(+1.0/0.0))) 215 expect(@trans.read(@trans.available)).to eq("\"NaN\"") 216 217 @prot.write_double((+1.0/0.0)) 218 expect(@trans.read(@trans.available)).to eq("\"Infinity\"") 219 220 @prot.write_double((-1.0/0.0)) 221 expect(@trans.read(@trans.available)).to eq("\"-Infinity\"") 222 end 223 224 if RUBY_VERSION >= '1.9' 225 it 'should write string' do 226 @prot.write_string('this is a test string') 227 a = @trans.read(@trans.available) 228 expect(a).to eq('"this is a test string"'.force_encoding(Encoding::BINARY)) 229 expect(a.encoding).to eq(Encoding::BINARY) 230 end 231 232 it 'should write string with unicode characters' do 233 @prot.write_string("this is a test string with unicode characters: \u20AC \u20AD") 234 a = @trans.read(@trans.available) 235 expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".force_encoding(Encoding::BINARY)) 236 expect(a.encoding).to eq(Encoding::BINARY) 237 end 238 else 239 it 'should write string' do 240 @prot.write_string('this is a test string') 241 expect(@trans.read(@trans.available)).to eq('"this is a test string"') 242 end 243 end 244 245 it "should write binary" do 246 @prot.write_binary("this is a base64 string") 247 expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"") 248 end 249 250 it "should write long binary" do 251 @prot.write_binary((0...256).to_a.pack('C*')) 252 expect(@trans.read(@trans.available)).to eq("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"") 253 end 254 255 it "should get type name for type id" do 256 expect {@prot.get_type_name_for_type_id(Thrift::Types::STOP)}.to raise_error(NotImplementedError) 257 expect {@prot.get_type_name_for_type_id(Thrift::Types::VOID)}.to raise_error(NotImplementedError) 258 expect(@prot.get_type_name_for_type_id(Thrift::Types::BOOL)).to eq("tf") 259 expect(@prot.get_type_name_for_type_id(Thrift::Types::BYTE)).to eq("i8") 260 expect(@prot.get_type_name_for_type_id(Thrift::Types::DOUBLE)).to eq("dbl") 261 expect(@prot.get_type_name_for_type_id(Thrift::Types::I16)).to eq("i16") 262 expect(@prot.get_type_name_for_type_id(Thrift::Types::I32)).to eq("i32") 263 expect(@prot.get_type_name_for_type_id(Thrift::Types::I64)).to eq("i64") 264 expect(@prot.get_type_name_for_type_id(Thrift::Types::STRING)).to eq("str") 265 expect(@prot.get_type_name_for_type_id(Thrift::Types::STRUCT)).to eq("rec") 266 expect(@prot.get_type_name_for_type_id(Thrift::Types::MAP)).to eq("map") 267 expect(@prot.get_type_name_for_type_id(Thrift::Types::SET)).to eq("set") 268 expect(@prot.get_type_name_for_type_id(Thrift::Types::LIST)).to eq("lst") 269 end 270 271 it "should get type id for type name" do 272 expect {@prot.get_type_id_for_type_name("pp")}.to raise_error(NotImplementedError) 273 expect(@prot.get_type_id_for_type_name("tf")).to eq(Thrift::Types::BOOL) 274 expect(@prot.get_type_id_for_type_name("i8")).to eq(Thrift::Types::BYTE) 275 expect(@prot.get_type_id_for_type_name("dbl")).to eq(Thrift::Types::DOUBLE) 276 expect(@prot.get_type_id_for_type_name("i16")).to eq(Thrift::Types::I16) 277 expect(@prot.get_type_id_for_type_name("i32")).to eq(Thrift::Types::I32) 278 expect(@prot.get_type_id_for_type_name("i64")).to eq(Thrift::Types::I64) 279 expect(@prot.get_type_id_for_type_name("str")).to eq(Thrift::Types::STRING) 280 expect(@prot.get_type_id_for_type_name("rec")).to eq(Thrift::Types::STRUCT) 281 expect(@prot.get_type_id_for_type_name("map")).to eq(Thrift::Types::MAP) 282 expect(@prot.get_type_id_for_type_name("set")).to eq(Thrift::Types::SET) 283 expect(@prot.get_type_id_for_type_name("lst")).to eq(Thrift::Types::LIST) 284 end 285 286 it "should read json syntax char" do 287 @trans.write('F') 288 expect {@prot.read_json_syntax_char('G')}.to raise_error(Thrift::ProtocolException) 289 @trans.write('H') 290 @prot.read_json_syntax_char('H') 291 end 292 293 it "should read json escape char" do 294 @trans.write('0054') 295 expect(@prot.read_json_escape_char).to eq('T') 296 297 @trans.write("\"\\\"\"") 298 expect(@prot.read_json_string(false)).to eq("\"") 299 300 @trans.write("\"\\\\\"") 301 expect(@prot.read_json_string(false)).to eq("\\") 302 303 @trans.write("\"\\/\"") 304 expect(@prot.read_json_string(false)).to eq("\/") 305 306 @trans.write("\"\\b\"") 307 expect(@prot.read_json_string(false)).to eq("\b") 308 309 @trans.write("\"\\f\"") 310 expect(@prot.read_json_string(false)).to eq("\f") 311 312 @trans.write("\"\\n\"") 313 expect(@prot.read_json_string(false)).to eq("\n") 314 315 @trans.write("\"\\r\"") 316 expect(@prot.read_json_string(false)).to eq("\r") 317 318 @trans.write("\"\\t\"") 319 expect(@prot.read_json_string(false)).to eq("\t") 320 end 321 322 it "should read json string" do 323 @trans.write("\"\\P") 324 expect {@prot.read_json_string(false)}.to raise_error(Thrift::ProtocolException) 325 326 @trans.write("\"this is a test string\"") 327 expect(@prot.read_json_string).to eq("this is a test string") 328 end 329 330 it "should read json base64" do 331 @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"") 332 expect(@prot.read_json_base64).to eq("this is a test string") 333 end 334 335 it "should is json numeric" do 336 expect(@prot.is_json_numeric("A")).to eq(false) 337 expect(@prot.is_json_numeric("+")).to eq(true) 338 expect(@prot.is_json_numeric("-")).to eq(true) 339 expect(@prot.is_json_numeric(".")).to eq(true) 340 expect(@prot.is_json_numeric("0")).to eq(true) 341 expect(@prot.is_json_numeric("1")).to eq(true) 342 expect(@prot.is_json_numeric("2")).to eq(true) 343 expect(@prot.is_json_numeric("3")).to eq(true) 344 expect(@prot.is_json_numeric("4")).to eq(true) 345 expect(@prot.is_json_numeric("5")).to eq(true) 346 expect(@prot.is_json_numeric("6")).to eq(true) 347 expect(@prot.is_json_numeric("7")).to eq(true) 348 expect(@prot.is_json_numeric("8")).to eq(true) 349 expect(@prot.is_json_numeric("9")).to eq(true) 350 expect(@prot.is_json_numeric("E")).to eq(true) 351 expect(@prot.is_json_numeric("e")).to eq(true) 352 end 353 354 it "should read json numeric chars" do 355 @trans.write("1.453E45T") 356 expect(@prot.read_json_numeric_chars).to eq("1.453E45") 357 end 358 359 it "should read json integer" do 360 @trans.write("1.45\"\"") 361 expect {@prot.read_json_integer}.to raise_error(Thrift::ProtocolException) 362 @prot.read_string 363 364 @trans.write("1453T") 365 expect(@prot.read_json_integer).to eq(1453) 366 end 367 368 it "should read json double" do 369 @trans.write("1.45e3e01\"\"") 370 expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException) 371 @prot.read_string 372 373 @trans.write("\"1.453e01\"") 374 expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException) 375 376 @trans.write("1.453e01\"\"") 377 expect(@prot.read_json_double).to eq(14.53) 378 @prot.read_string 379 380 @trans.write("\"NaN\"") 381 expect(@prot.read_json_double.nan?).to eq(true) 382 383 @trans.write("\"Infinity\"") 384 expect(@prot.read_json_double).to eq(+1.0/0.0) 385 386 @trans.write("\"-Infinity\"") 387 expect(@prot.read_json_double).to eq(-1.0/0.0) 388 end 389 390 it "should read json object start" do 391 @trans.write("{") 392 expect(@prot.read_json_object_start).to eq(nil) 393 end 394 395 it "should read json object end" do 396 @trans.write("}") 397 expect(@prot.read_json_object_end).to eq(nil) 398 end 399 400 it "should read json array start" do 401 @trans.write("[") 402 expect(@prot.read_json_array_start).to eq(nil) 403 end 404 405 it "should read json array end" do 406 @trans.write("]") 407 expect(@prot.read_json_array_end).to eq(nil) 408 end 409 410 it "should read_message_begin" do 411 @trans.write("[2,") 412 expect {@prot.read_message_begin}.to raise_error(Thrift::ProtocolException) 413 414 @trans.write("[1,\"name\",12,32\"\"") 415 expect(@prot.read_message_begin).to eq(["name", 12, 32]) 416 end 417 418 it "should read message end" do 419 @trans.write("]") 420 expect(@prot.read_message_end).to eq(nil) 421 end 422 423 it "should read struct begin" do 424 @trans.write("{") 425 expect(@prot.read_struct_begin).to eq(nil) 426 end 427 428 it "should read struct end" do 429 @trans.write("}") 430 expect(@prot.read_struct_end).to eq(nil) 431 end 432 433 it "should read field begin" do 434 @trans.write("1{\"rec\"") 435 expect(@prot.read_field_begin).to eq([nil, 12, 1]) 436 end 437 438 it "should read field end" do 439 @trans.write("}") 440 expect(@prot.read_field_end).to eq(nil) 441 end 442 443 it "should read map begin" do 444 @trans.write("[\"rec\",\"lst\",2,{") 445 expect(@prot.read_map_begin).to eq([12, 15, 2]) 446 end 447 448 it "should read map end" do 449 @trans.write("}]") 450 expect(@prot.read_map_end).to eq(nil) 451 end 452 453 it "should read list begin" do 454 @trans.write("[\"rec\",2\"\"") 455 expect(@prot.read_list_begin).to eq([12, 2]) 456 end 457 458 it "should read list end" do 459 @trans.write("]") 460 expect(@prot.read_list_end).to eq(nil) 461 end 462 463 it "should read set begin" do 464 @trans.write("[\"rec\",2\"\"") 465 expect(@prot.read_set_begin).to eq([12, 2]) 466 end 467 468 it "should read set end" do 469 @trans.write("]") 470 expect(@prot.read_set_end).to eq(nil) 471 end 472 473 it "should read bool" do 474 @trans.write("0\"\"") 475 expect(@prot.read_bool).to eq(false) 476 @prot.read_string 477 478 @trans.write("1\"\"") 479 expect(@prot.read_bool).to eq(true) 480 end 481 482 it "should read byte" do 483 @trans.write("60\"\"") 484 expect(@prot.read_byte).to eq(60) 485 end 486 487 it "should read i16" do 488 @trans.write("1000\"\"") 489 expect(@prot.read_i16).to eq(1000) 490 end 491 492 it "should read i32" do 493 @trans.write("3000000000\"\"") 494 expect(@prot.read_i32).to eq(3000000000) 495 end 496 497 it "should read i64" do 498 @trans.write("6000000000\"\"") 499 expect(@prot.read_i64).to eq(6000000000) 500 end 501 502 it "should read double" do 503 @trans.write("12.23\"\"") 504 expect(@prot.read_double).to eq(12.23) 505 end 506 507 if RUBY_VERSION >= '1.9' 508 it 'should read string' do 509 @trans.write('"this is a test string"'.force_encoding(Encoding::BINARY)) 510 a = @prot.read_string 511 expect(a).to eq('this is a test string') 512 expect(a.encoding).to eq(Encoding::UTF_8) 513 end 514 515 it 'should read string with unicode characters' do 516 @trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.force_encoding(Encoding::BINARY)) 517 a = @prot.read_string 518 expect(a).to eq("this is a test string with unicode characters: \u20AC \u20AD") 519 expect(a.encoding).to eq(Encoding::UTF_8) 520 end 521 else 522 it 'should read string' do 523 @trans.write('"this is a test string"') 524 expect(@prot.read_string).to eq('this is a test string') 525 end 526 end 527 528 it "should read binary" do 529 @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"") 530 expect(@prot.read_binary).to eq("this is a test string") 531 end 532 533 it "should read long binary" do 534 @trans.write("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"") 535 expect(@prot.read_binary.bytes.to_a).to eq((0...256).to_a) 536 end 537 538 it "should provide a reasonable to_s" do 539 expect(@prot.to_s).to eq("json(memory)") 540 end 541 end 542 543 describe Thrift::JsonProtocolFactory do 544 it "should create a JsonProtocol" do 545 expect(Thrift::JsonProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::JsonProtocol) 546 end 547 548 it "should provide a reasonable to_s" do 549 expect(Thrift::JsonProtocolFactory.new.to_s).to eq("json") 550 end 551 end 552end 553