From dbed04b20786d02c36e8e93667fe9608a77e3dc3 Mon Sep 17 00:00:00 2001 From: leobessa Date: Fri, 2 Aug 2013 14:36:46 -0300 Subject: [PATCH] Fixed Decoding#read_long! and Decoding#read_int! for negative values - Added specs for bigint, counter and int decoding. - Added unit test to Decoding#read_int! for negative values --- lib/cql/protocol/decoding.rb | 16 +++++-- spec/cql/protocol/decoding_spec.rb | 14 +++++- spec/integration/protocol_spec.rb | 70 ++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 5 deletions(-) diff --git a/lib/cql/protocol/decoding.rb b/lib/cql/protocol/decoding.rb index cdf2743..dd1a386 100644 --- a/lib/cql/protocol/decoding.rb +++ b/lib/cql/protocol/decoding.rb @@ -38,8 +38,14 @@ def read_decimal!(buffer, length=buffer.length) end def read_long!(buffer) - top, bottom = buffer.read(8).unpack(Formats::TWO_INTS_FORMAT) - (top << 32) | bottom + hi, lo = buffer.read(8).unpack(Formats::TWO_INTS_FORMAT) + if (hi > 0x7fffffff) + hi ^= 0xffffffff + lo ^= 0xffffffff + 0 - (hi << 32) - lo - 1 + else + (hi << 32) + lo + end rescue RangeError => e raise DecodingError, e.message, e.backtrace end @@ -57,7 +63,11 @@ def read_float!(buffer) end def read_int!(buffer) - buffer.read_int + val = buffer.read_int + if (val > 0x7fffffff) + val = 0 - ((val - 1) ^ 0xffffffff) + end + val rescue RangeError => e raise DecodingError, "Not enough bytes available to decode an int: #{e.message}", e.backtrace end diff --git a/spec/cql/protocol/decoding_spec.rb b/spec/cql/protocol/decoding_spec.rb index e108e79..02add3a 100644 --- a/spec/cql/protocol/decoding_spec.rb +++ b/spec/cql/protocol/decoding_spec.rb @@ -79,11 +79,16 @@ module Protocol end describe '#read_long!' do - it 'decodes a long' do + it 'decodes a positive long' do buffer = ByteBuffer.new("\x00\x00\xca\xfe\xba\xbe\x00\x00") Decoding.read_long!(buffer).should == 0x0000cafebabe0000 end + it 'decodes a negative long' do + buffer = ByteBuffer.new("\xff\xff\xff\xff\xff\xff\xff\xff") + Decoding.read_long!(buffer).should == -1 + end + it 'consumes the bytes' do buffer = ByteBuffer.new("\xca\xfe\xba\xbe\xca\xfe\xba\xbe\xca\xfe\xba\xbe") Decoding.read_long!(buffer) @@ -137,10 +142,15 @@ module Protocol ByteBuffer.new("\x00\xff\x00\xff") end - it 'decodes an int' do + it 'decodes a positive int' do Decoding.read_int!(buffer).should == 0x00ff00ff end + it 'decodes a negative int' do + buffer = ByteBuffer.new("\xff\xff\xff\xff") + Decoding.read_int!(buffer).should == -1 + end + it 'consumes the bytes' do buffer << "\xab\xcd" Decoding.read_int!(buffer) diff --git a/spec/integration/protocol_spec.rb b/spec/integration/protocol_spec.rb index b1eea13..966c157 100644 --- a/spec/integration/protocol_spec.rb +++ b/spec/integration/protocol_spec.rb @@ -285,6 +285,76 @@ def in_keyspace_with_counters_table end end + it 'decodes positive counters' do + in_keyspace_with_counters_table do + max_long = (1 << 63) -1 + response = query(%) + response = query(%, :quorum) + response.rows.should == [ + {'id' => 'negative', 'c1' => -1 , 'c2' => min_long} + ] + end + end + + it 'decodes positive bigints' do + in_keyspace do + max_long = (1 << 63) -1 + response = query('CREATE TABLE stuff (id VARCHAR, c1 bigint, c2 bigint, PRIMARY KEY (id))') + response = query(%) + response = query(%, :quorum) + response.rows.should == [ + {'id' => 'stuff', 'c1' => -1, 'c2' => min_long} + ] + end + end + + it 'decodes positive ints' do + in_keyspace do + max_int = (1 << 31) -1 + response = query('CREATE TABLE stuff (id VARCHAR, c1 int, c2 int, PRIMARY KEY (id))') + response = query(%) + response = query(%, :quorum) + response.rows.should == [ + {'id' => 'stuff', 'c1' => -1, 'c2' => min_int} + ] + end + end + it 'sends a DELETE command' do in_keyspace_with_table do response = query(%)