Permalink
Fetching contributors…
Cannot retrieve contributors at this time
324 lines (270 sloc) 10.5 KB
# encoding: utf-8
require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
include CassandraCQL
describe "Validation Roundtrip tests" do
before(:each) do
@connection = setup_cassandra_connection
end
def create_and_fetch_column(column_family, value)
@connection.execute("INSERT INTO #{column_family} (id, test_column) VALUES (?, ?)", 'test', value)
res = @connection.execute("SELECT test_column FROM #{column_family} WHERE id = ?", 'test')
return res.fetch[0]
end
def reset_column_family(name, test_column_type, opts="")
if column_family_exists?(@connection, name)
@connection.execute("DROP COLUMNFAMILY #{name}")
end
@connection.execute("CREATE COLUMNFAMILY #{name} (id text PRIMARY KEY, test_column #{test_column_type}) #{opts}")
end
def change_column_type_and_raise_exception(cf_name, type, value)
@connection.execute("ALTER COLUMNFAMILY #{cf_name} ADD broken_column varchar")
@connection.execute("INSERT INTO #{cf_name} (id, broken_column) values (?, ?)", 'test', value)
@connection.execute("ALTER COLUMNFAMILY #{cf_name} ALTER broken_column TYPE #{type}")
expect {
@connection.execute("SELECT id, broken_column FROM #{cf_name} WHERE id=?", 'test').fetch['broken_column']
}.to raise_error CassandraCQL::Error::CastException
end
context "with ascii validation" do
let(:cf_name) { "validation_cf_ascii" }
before(:each) { reset_column_family(cf_name, 'ascii') }
it "should return an ascii string" do
create_and_fetch_column(cf_name, "test string").should eq("test string")
end
end
context "with bigint validation" do
let(:cf_name) { "validation_cf_bigint" }
before(:each) { reset_column_family(cf_name, 'bigint') }
def test_for_value(value)
create_and_fetch_column(cf_name, value).should eq(value)
create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
end
it "should properly convert integer values that fit into 1 byte" do
test_for_value(1)
end
it "should properly convert integer values that fit into 2 bytes" do
test_for_value(2**8 + 80)
end
it "should properly convert integer values that fit into 3 bytes" do
test_for_value(2**16 + 622)
end
it "should properly convert integer values that fit into 4 bytes" do
test_for_value(2**24 + 45820)
end
it "should properly convert integer values that fit into 5 bytes" do
test_for_value(2**32 + 618387)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'bigint', nil)
end
end
context "with blob validation" do
let(:cf_name) { "validation_cf_blob" }
if CASSANDRA_VERSION.to_f == 0.8
before(:each) { reset_column_family(cf_name, 'bytea') }
else
before(:each) { reset_column_family(cf_name, 'blob') }
end
it "should return a blob" do
bytes = "binary\x00"
bytes = bytes.force_encoding('ASCII-8BIT') if RUBY_VERSION >= "1.9"
create_and_fetch_column(cf_name, bytes).should eq(bytes)
end
end
context "with boolean validation" do
let(:cf_name) { "validation_cf_boolean" }
before(:each) { reset_column_family(cf_name, 'boolean') }
it "should return true" do
create_and_fetch_column(cf_name, true).should be_true
end
it "should return false" do
create_and_fetch_column(cf_name, false).should be_false
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'boolean', nil)
end
end
context "with counter validation", :cql_version => '2.0.0' do
let(:cf_name) { "validation_cf_counter" }
before(:each) {
if !@connection.schema.column_family_names.include?(cf_name)
@connection.execute("CREATE COLUMNFAMILY #{cf_name} (id text PRIMARY KEY) WITH default_validation=CounterColumnType")
end
@connection.execute("TRUNCATE #{cf_name}")
}
it "should increment a few times" do
10.times do |i|
@connection.execute("UPDATE #{cf_name} SET test=test + 1 WHERE id=?", 'test_key')
@connection.execute("SELECT test FROM #{cf_name} WHERE id=?", 'test_key').fetch[0].should eq(i+1)
end
end
it "should decrement a few times" do
10.times do |i|
@connection.execute("UPDATE #{cf_name} SET test=test - 1 WHERE id=?", 'test_key')
@connection.execute("SELECT test FROM #{cf_name} WHERE id=?", 'test_key').fetch[0].should eq((i+1)*-1)
end
end
end
if CASSANDRA_VERSION.to_f >= 1.0
context "with decimal validation" do
let(:cf_name) { "validation_cf_decimal" }
before(:each) { reset_column_family(cf_name, 'decimal') }
def test_for_value(value)
create_and_fetch_column(cf_name, value).should eq(value)
create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
end
it "should return a small decimal" do
test_for_value(15.333)
end
it "should return a huge decimal" do
test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'decimal', nil)
end
end
end
context "with double validation" do
let(:cf_name) { "validation_cf_double" }
before(:each) { reset_column_family(cf_name, 'double') }
def test_for_value(value)
create_and_fetch_column(cf_name, value).should be_within(0.1).of(value)
create_and_fetch_column(cf_name, value*-1).should be_within(0.1).of(-1*value)
end
it "should properly convert some float values" do
test_for_value(1.125)
test_for_value(384.125)
test_for_value(65540.125)
test_for_value(16777217.125)
test_for_value(1099511627776.125)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'double', nil)
end
end
context "with float validation" do
let(:cf_name) { "validation_cf_float" }
before(:each) { reset_column_family(cf_name, 'float') }
def test_for_value(value)
create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
create_and_fetch_column(cf_name, value).should eq(value)
end
it "should properly convert some float values" do
test_for_value(1.125)
test_for_value(384.125)
test_for_value(65540.125)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'float', nil)
end
end
context "with int validation" do
let(:cf_name) { "validation_cf_int" }
before(:each) { reset_column_family(cf_name, 'int') }
def test_for_value(value)
create_and_fetch_column(cf_name, value).should eq(value)
create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
end
it "should properly convert integer values that fit into 1 byte" do
test_for_value(1)
end
it "should properly convert integer values that fit into 2 bytes" do
test_for_value(2**8 + 80)
end
it "should properly convert integer values that fit into 3 bytes" do
test_for_value(2**16 + 622)
end
it "should properly convert integer values that fit into 4 bytes" do
test_for_value(2**24 + 45820)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'int', nil)
end
end
context "with text validation" do
let(:cf_name) { "validation_cf_text" }
before(:each) { reset_column_family(cf_name, 'varchar') }
it "should return a non-multibyte string" do
create_and_fetch_column(cf_name, "snark").should eq("snark")
end
it "should return a multibyte string" do
if RUBY_VERSION >= "1.9"
create_and_fetch_column(cf_name, "sn\xC3\xA5rk".force_encoding('UTF-8')).should eq("sn\xC3\xA5rk".force_encoding('UTF-8'))
else
create_and_fetch_column(cf_name, "snårk").should eq("snårk")
end
end
end
context "with timestamp validation" do
let(:cf_name) { "validation_cf_timestamp" }
if CASSANDRA_VERSION.to_f == 0.8
before(:each) { reset_column_family(cf_name, 'date') }
else
before(:each) { reset_column_family(cf_name, 'timestamp') }
end
it "should return a timestamp" do
ts = Time.new
res = create_and_fetch_column(cf_name, ts)
res.to_f.should be_within(0.001).of(ts.to_f)
res.class.should eq(Time)
end
it "should return a timestamp given a date" do
date = Date.today
res = create_and_fetch_column(cf_name, date)
[:year, :month, :day].each do |sym|
res.send(sym).should eq(date.send(sym))
end
res.class.should eq(Time)
end
it "should raise a CastException" do
if CASSANDRA_VERSION.to_f == 0.8
change_column_type_and_raise_exception(cf_name, 'date', nil)
else
change_column_type_and_raise_exception(cf_name, 'timestamp', nil)
end
end
end
context "with uuid validation" do
let(:cf_name) { "validation_cf_uuid" }
before(:each) { reset_column_family(cf_name, 'uuid') }
it "should return a uuid" do
uuid = UUID.new
create_and_fetch_column(cf_name, uuid).should eq(uuid)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'uuid', nil)
end
end
context "with varchar validation" do
let(:cf_name) { "validation_cf_varchar" }
before(:each) { reset_column_family(cf_name, 'varchar') }
it "should return a non-multibyte string" do
create_and_fetch_column(cf_name, "snark").should eq("snark")
end
it "should return a multibyte string" do
create_and_fetch_column(cf_name, "snårk").should eq("snårk")
end
end
context "with varint validation" do
let(:cf_name) { "validation_cf_varint" }
before(:each) { reset_column_family(cf_name, 'varint') }
def test_for_value(value)
create_and_fetch_column(cf_name, value).should eq(value)
create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
end
it "should properly convert integer values that fit into 1 byte" do
test_for_value(1)
end
it "should properly convert integer values that fit into 2 bytes" do
test_for_value(2**8 + 80)
end
it "should properly convert integer values that fit into 3 bytes" do
test_for_value(2**16 + 622)
end
it "should properly convert integer values that fit into more than 8 bytes" do
test_for_value(2**256)
end
it "should raise a CastException" do
change_column_type_and_raise_exception(cf_name, 'varint', nil)
end
end
end