hallelujah-cassandra-cql 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +203 -0
  4. data/README.rdoc +71 -0
  5. data/Rakefile +151 -0
  6. data/hallelujah-cassandra-cql.gemspec +33 -0
  7. data/lib/cassandra-cql.rb +49 -0
  8. data/lib/cassandra-cql/0.8.rb +7 -0
  9. data/lib/cassandra-cql/0.8/result.rb +23 -0
  10. data/lib/cassandra-cql/0.8/statement.rb +38 -0
  11. data/lib/cassandra-cql/1.0.rb +7 -0
  12. data/lib/cassandra-cql/1.0/result.rb +6 -0
  13. data/lib/cassandra-cql/1.0/statement.rb +6 -0
  14. data/lib/cassandra-cql/1.1.rb +7 -0
  15. data/lib/cassandra-cql/1.1/result.rb +6 -0
  16. data/lib/cassandra-cql/1.1/statement.rb +6 -0
  17. data/lib/cassandra-cql/database.rb +127 -0
  18. data/lib/cassandra-cql/result.rb +133 -0
  19. data/lib/cassandra-cql/row.rb +54 -0
  20. data/lib/cassandra-cql/schema.rb +108 -0
  21. data/lib/cassandra-cql/statement.rb +116 -0
  22. data/lib/cassandra-cql/types/abstract_type.rb +47 -0
  23. data/lib/cassandra-cql/types/ascii_type.rb +25 -0
  24. data/lib/cassandra-cql/types/boolean_type.rb +25 -0
  25. data/lib/cassandra-cql/types/bytes_type.rb +21 -0
  26. data/lib/cassandra-cql/types/date_type.rb +25 -0
  27. data/lib/cassandra-cql/types/decimal_type.rb +25 -0
  28. data/lib/cassandra-cql/types/double_type.rb +25 -0
  29. data/lib/cassandra-cql/types/float_type.rb +25 -0
  30. data/lib/cassandra-cql/types/integer_type.rb +27 -0
  31. data/lib/cassandra-cql/types/long_type.rb +27 -0
  32. data/lib/cassandra-cql/types/utf8_type.rb +25 -0
  33. data/lib/cassandra-cql/types/uuid_type.rb +27 -0
  34. data/lib/cassandra-cql/utility.rb +37 -0
  35. data/lib/cassandra-cql/uuid.rb +21 -0
  36. data/lib/cassandra-cql/version.rb +19 -0
  37. data/spec/column_family_spec.rb +105 -0
  38. data/spec/comparator_spec.rb +249 -0
  39. data/spec/conf/0.8/cassandra.in.sh +41 -0
  40. data/spec/conf/0.8/cassandra.yaml +61 -0
  41. data/spec/conf/0.8/log4j-server.properties +40 -0
  42. data/spec/conf/0.8/schema.txt +10 -0
  43. data/spec/conf/1.0/cassandra.in.sh +41 -0
  44. data/spec/conf/1.0/cassandra.yaml +416 -0
  45. data/spec/conf/1.0/log4j-server.properties +40 -0
  46. data/spec/conf/1.0/schema.txt +10 -0
  47. data/spec/conf/1.1/cassandra.in.sh +41 -0
  48. data/spec/conf/1.1/cassandra.yaml +560 -0
  49. data/spec/conf/1.1/log4j-server.properties +44 -0
  50. data/spec/conf/1.1/schema.txt +10 -0
  51. data/spec/database_spec.rb +25 -0
  52. data/spec/result_spec.rb +173 -0
  53. data/spec/row_spec.rb +49 -0
  54. data/spec/rowkey_spec.rb +233 -0
  55. data/spec/schema_spec.rb +51 -0
  56. data/spec/spec_helper.rb +30 -0
  57. data/spec/statement_spec.rb +226 -0
  58. data/spec/utility_spec.rb +26 -0
  59. data/spec/uuid_spec.rb +26 -0
  60. data/spec/validation_spec.rb +272 -0
  61. data/vendor/0.8/gen-rb/cassandra.rb +2210 -0
  62. data/vendor/0.8/gen-rb/cassandra_constants.rb +10 -0
  63. data/vendor/0.8/gen-rb/cassandra_types.rb +811 -0
  64. data/vendor/1.0/gen-rb/cassandra.rb +2212 -0
  65. data/vendor/1.0/gen-rb/cassandra_constants.rb +10 -0
  66. data/vendor/1.0/gen-rb/cassandra_types.rb +854 -0
  67. data/vendor/1.1/gen-rb/cassandra.rb +2511 -0
  68. data/vendor/1.1/gen-rb/cassandra_constants.rb +13 -0
  69. data/vendor/1.1/gen-rb/cassandra_types.rb +928 -0
  70. metadata +230 -0
@@ -0,0 +1,51 @@
1
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
2
+ include CassandraCQL
3
+
4
+ describe "Schema class" do
5
+ before(:each) do
6
+ @connection = setup_cassandra_connection
7
+ @connection.execute("USE system")
8
+ end
9
+
10
+ context "initialize" do
11
+ it "should set a thrift schema object" do
12
+ @connection.schema.schema.should be_kind_of(CassandraCQL::Thrift::KsDef)
13
+ end
14
+
15
+ it "should set column family hash" do
16
+ @connection.schema.column_families.should be_kind_of(Hash)
17
+ end
18
+
19
+ it "should set column family hash" do
20
+ @connection.schema.column_families.should be_kind_of(Hash)
21
+ end
22
+ end
23
+
24
+ it "should method_missing" do
25
+ expect {
26
+ @connection.schema.this_method_does_not_exist
27
+ }.to raise_error NoMethodError
28
+ end
29
+
30
+ context "name" do
31
+ it "should return keyspace name" do
32
+ @connection.schema.name.should eq('system')
33
+ end
34
+ end
35
+
36
+ context "to_s" do
37
+ it "should return keyspace name" do
38
+ @connection.schema.to_s.should eq(@connection.schema.name)
39
+ end
40
+ end
41
+
42
+ context "column_family_names" do
43
+ it "should return cf_def names" do
44
+ @connection.schema.column_family_names.sort.should eq(@connection.schema.schema.cf_defs.map(&:name).sort)
45
+ end
46
+
47
+ it "should be the same as tables" do
48
+ @connection.schema.column_family_names.should eq(@connection.schema.tables)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,30 @@
1
+ require 'yaml'
2
+ require 'rspec'
3
+
4
+ CASSANDRA_VERSION = ENV['CASSANDRA_VERSION'] || '1.0' unless defined?(CASSANDRA_VERSION)
5
+
6
+ $LOAD_PATH << "#{File.expand_path(File.dirname(__FILE__))}/../lib"
7
+ require "cassandra-cql/#{CASSANDRA_VERSION}"
8
+
9
+ def yaml_fixture(file)
10
+ if file.kind_of?(Symbol)
11
+ file = "#{file}.yaml"
12
+ elsif file !~ /\.yaml$/
13
+ file = "#{file}.yaml"
14
+ end
15
+ YAML::load_file(File.dirname(__FILE__) + "/fixtures/#{file}")
16
+ end
17
+
18
+ def setup_cassandra_connection
19
+ @connection ||= CassandraCQL::Database.new(["127.0.0.1:9160"], {}, :retries => 2, :timeout => 1)
20
+ if !@connection.keyspaces.map(&:name).include?("CassandraCQLTestKeyspace")
21
+ @connection.execute("CREATE KEYSPACE CassandraCQLTestKeyspace WITH strategy_class='org.apache.cassandra.locator.SimpleStrategy' AND strategy_options:replication_factor=1")
22
+ end
23
+ @connection.execute("USE CassandraCQLTestKeyspace")
24
+
25
+ @connection
26
+ end
27
+ require 'simplecov'
28
+ SimpleCov.start do
29
+ add_filter "/spec/"
30
+ end
@@ -0,0 +1,226 @@
1
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
2
+ include CassandraCQL
3
+
4
+ describe "initialize" do
5
+ it "should set a handle and prepare statement" do
6
+ statement = "use keyspace1"
7
+ handle = double("Database")
8
+ sth = Statement.new(handle, statement)
9
+ sth.statement.should eq(statement)
10
+ sth.instance_variable_get("@handle").should eq(handle)
11
+ end
12
+ end
13
+
14
+ describe "execute" do
15
+ context "when performing keyspace operations" do
16
+ before(:each) do
17
+ @connection = setup_cassandra_connection
18
+ end
19
+
20
+ it "should set keyspace without compression" do
21
+ @connection.keyspace.should_not eq('system')
22
+ stmt = @connection.prepare("use system")
23
+ stmt.execute([], :compression => false).should be_nil
24
+ @connection.keyspace.should eq('system')
25
+ end
26
+
27
+ it "should set keyspace with compression" do
28
+ @connection.keyspace.should_not eq('system')
29
+ stmt = @connection.prepare("use system")
30
+ stmt.execute([], :compression => true).should be_nil
31
+ @connection.keyspace.should eq('system')
32
+ end
33
+
34
+ it "should set keyspace to nil when deleting keyspace" do
35
+ @connection.execute("DROP KEYSPACE #{@connection.keyspace}").should be_nil
36
+ @connection.keyspace.should be_nil
37
+ end
38
+ end
39
+
40
+ context "when performing void-returning column_family operations" do
41
+ before(:each) do
42
+ @connection = setup_cassandra_connection
43
+ if !@connection.schema.column_family_names.include?('colfam_ops')
44
+ @connection.execute("CREATE COLUMNFAMILY colfam_ops (id varchar PRIMARY KEY)")
45
+ else
46
+ @connection.execute("TRUNCATE colfam_ops")
47
+ end
48
+ end
49
+
50
+ it "should return nil when inserting" do
51
+ @connection.execute("INSERT INTO colfam_ops (id, column) VALUES (?, ?)", "key", "value").should be_nil
52
+ end
53
+
54
+ it "should return nil when updating" do
55
+ @connection.execute("UPDATE colfam_ops SET column=? WHERE id=?", "value", "key").should be_nil
56
+ end
57
+
58
+ it "should return nil when deleting" do
59
+ @connection.execute("DELETE FROM colfam_ops WHERE id=?", "key").should be_nil
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "escape" do
65
+ it "should escape quotes" do
66
+ Statement.escape(%q{'}).should eq(%q{''})
67
+ Statement.escape(%q{\'}).should eq(%q{\''})
68
+ Statement.escape(%q{''}).should eq(%q{''''})
69
+ end
70
+ end
71
+
72
+ describe "quote" do
73
+ context "with a string" do
74
+ it "should add quotes" do
75
+ Statement.quote("test").should eq("'test'")
76
+ end
77
+ end
78
+
79
+ context "with an integer" do
80
+ it "should not add quotes" do
81
+ Statement.quote(15).should eq(15)
82
+ end
83
+ end
84
+
85
+ context "with an array" do
86
+ it "should return a comma-separated list" do
87
+ Statement.quote([1, 2, 3]).should eq("1,2,3")
88
+ Statement.quote(["a", "b''", "c"]).should eq("'a','b''','c'")
89
+ end
90
+ end
91
+
92
+ context "with an unsupported object" do
93
+ it "should raise an exception" do
94
+ expect {
95
+ Statement.quote(Time.new)
96
+ }.to raise_error(CassandraCQL::Error::UnescapableObject)
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "cast_to_cql" do
102
+ context "with a Time object" do
103
+ it "should return a Time object with the number of microseconds since epoch" do
104
+ ts = Time.new - 86400 # set it to yesterday just to be sure no defaulting to today misses an error
105
+ long = Statement.cast_to_cql(ts)
106
+ long.should be_kind_of(Integer)
107
+ Time.at(long / 1000.0).to_f.should be_within(0.001).of(ts.to_f)
108
+ end
109
+ end
110
+
111
+ context "with a Date object" do
112
+ it "should return a corresponding Time object" do
113
+ date = Date.today << 1
114
+ str = Statement.cast_to_cql(date)
115
+ str.should eq(date.strftime('%Y-%m-%d'))
116
+ end
117
+ end
118
+
119
+ context "with a Fixnum object" do
120
+ it "should return the same object" do
121
+ Statement.cast_to_cql(15).should eq(15)
122
+ end
123
+ end
124
+
125
+ context "with a UUID object" do
126
+ it "should return the a guid" do
127
+ uuid = UUID.new
128
+ guid = Statement.cast_to_cql(uuid)
129
+ guid.should eq(uuid.to_guid)
130
+ end
131
+ end
132
+
133
+ context "with a String without quotes" do
134
+ it "should return a copy of itself" do
135
+ str = "This is a string"
136
+ new_str = Statement.cast_to_cql(str)
137
+ str.should eq(str)
138
+ new_str.object_id.should_not eq(str.object_id)
139
+ end
140
+ end
141
+
142
+ context "with a String with quotes" do
143
+ it "should return a quoted version" do
144
+ str = "This is a ' string"
145
+ new_str = Statement.cast_to_cql(str)
146
+ new_str.should_not eq(str)
147
+ new_str.should eq(Statement.escape(str))
148
+ end
149
+ end
150
+
151
+ context "with binary data" do
152
+ it "should return an unpacked version" do
153
+ bytes = "binary\x00"
154
+ bytes = bytes.force_encoding('ASCII-8BIT') if RUBY_VERSION >= "1.9"
155
+ new_data = Statement.cast_to_cql(bytes)
156
+ new_data.should_not eq(bytes)
157
+ [new_data].pack('H*').should eq(bytes)
158
+ end
159
+ end
160
+
161
+ context "with an array of Fixnums" do
162
+ it "should equal itself" do
163
+ arr = [1, 2, 3]
164
+ Statement.cast_to_cql(arr).should eq(arr)
165
+ end
166
+ end
167
+
168
+ context "with an array of Strings" do
169
+ it "should return quoted versions of itself" do
170
+ arr = ["test", "'"]
171
+ res = Statement.cast_to_cql(arr)
172
+ arr.map { |o| Statement.cast_to_cql(o) }.should eq(res)
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "sanitize" do
178
+ context "with no bind vars" do
179
+ it "should return itself" do
180
+ Statement.sanitize("use keyspace").should eq("use keyspace")
181
+ end
182
+ end
183
+
184
+ context "when expecting bind vars" do
185
+ it "should raise an exception with bind variable mismatch" do
186
+ expect {
187
+ Statement.sanitize("use keyspace ?")
188
+ }.to raise_error(Error::InvalidBindVariable)
189
+
190
+ expect {
191
+ Statement.sanitize("use keyspace ?", ['too', 'many'])
192
+ }.to raise_error(Error::InvalidBindVariable)
193
+ end
194
+
195
+ it "should not raise an exception with matching bind vars" do
196
+ expect {
197
+ Statement.sanitize("use keyspace ?", ["test"]).should eq("use keyspace 'test'")
198
+ }.to_not raise_error(Error::InvalidBindVariable)
199
+ end
200
+
201
+ it "should have bind vars in the right order" do
202
+ expect {
203
+ Statement.sanitize("use keyspace ? with randomness (?)", ["test", "stuff"]).should eq("use keyspace 'test' with randomness ('stuff')")
204
+ }.to_not raise_error(Error::InvalidBindVariable)
205
+ end
206
+
207
+ it "should not double-escape the single quotes in your string" do
208
+ Statement.sanitize(
209
+ "insert into keyspace (key, ?) values (?)", ["vanilla", %Q{I\'m a string with \'cool\' quotes}]
210
+ ).should eq("insert into keyspace (key, 'vanilla') values ('I''m a string with ''cool'' quotes')")
211
+ end
212
+
213
+ it "should handle numbers and stuff appropriately" do
214
+ Statement.sanitize(
215
+ "insert into keyspace (key, ?) values (?)", [488, 60.368]
216
+ ).should eq("insert into keyspace (key, 488) values (60.368)")
217
+ end
218
+
219
+ end
220
+ end
221
+
222
+ describe "finish" do
223
+ it "should just return true .. nothing to clean up yet" do
224
+ Statement.new(nil, 'whatever').finish.should be_true
225
+ end
226
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
3
+ include CassandraCQL
4
+
5
+ describe "compress" do
6
+ it "should return some valid gzipped stuff" do
7
+ stuff = "This is some stuff"
8
+ bytes = Utility.compress(stuff)
9
+ Utility.binary_data?(bytes).should be_true
10
+ Utility.decompress(bytes).should eq(stuff)
11
+ end
12
+
13
+ it "should be binary data" do
14
+ if RUBY_VERSION >= "1.9"
15
+ Utility.binary_data?("binary\x00".force_encoding('ASCII-8BIT')).should be_true
16
+ else
17
+ Utility.binary_data?("binary\x00").should be_true
18
+ end
19
+ end
20
+
21
+ it "should not be binary data" do
22
+ Utility.binary_data?("test").should_not be_true
23
+ Utility.binary_data?("snårk").should_not be_true
24
+ end
25
+ end
26
+
@@ -0,0 +1,26 @@
1
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
2
+ include CassandraCQL
3
+
4
+ describe "UUID" do
5
+ it "should respond_to to_guid" do
6
+ UUID.new.respond_to?(:to_guid)
7
+ end
8
+
9
+ it "should respond_to to_time" do
10
+ UUID.new.respond_to?(:to_time)
11
+ end
12
+
13
+ it "should instantiate from raw bytes" do
14
+ UUID.new("\252}\303\374\3137\021\340\237\214\251}\315\351 ]")
15
+ end
16
+
17
+ it "should instantiate from a Time object" do
18
+ ts = Time.new
19
+ UUID.new(ts).to_time.should eq(ts)
20
+ end
21
+
22
+ it "should turn have a to_time class method that takes bytes" do
23
+ UUID.to_time("\252}\303\374\3137\021\340\237\214\251}\315\351 ]").should be_kind_of(Time)
24
+ end
25
+ end
26
+
@@ -0,0 +1,272 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('spec_helper.rb', File.dirname(__FILE__))
3
+ include CassandraCQL
4
+
5
+ describe "Validation Roundtrip tests" do
6
+ before(:each) do
7
+ @connection = setup_cassandra_connection
8
+ end
9
+
10
+ def create_and_fetch_column(column_family, value)
11
+ @connection.execute("insert into #{column_family} (id, test_column) values (?, ?)", 'test', value)
12
+ res = @connection.execute("select test_column from #{column_family} where id = ?", 'test')
13
+ return res.fetch[0]
14
+ end
15
+
16
+ def create_column_family(name, test_column_type, opts="")
17
+ if !@connection.schema.column_family_names.include?(name)
18
+ @connection.execute("CREATE COLUMNFAMILY #{name} (id text PRIMARY KEY, test_column #{test_column_type}) #{opts}")
19
+ end
20
+ end
21
+
22
+ context "with ascii validation" do
23
+ let(:cf_name) { "validation_cf_ascii" }
24
+ before(:each) { create_column_family(cf_name, 'ascii') }
25
+
26
+ it "should return an ascii string" do
27
+ create_and_fetch_column(cf_name, "test string").should eq("test string")
28
+ end
29
+ end
30
+
31
+ context "with bigint validation" do
32
+ let(:cf_name) { "validation_cf_bigint" }
33
+ before(:each) { create_column_family(cf_name, 'bigint') }
34
+
35
+ def test_for_value(value)
36
+ create_and_fetch_column(cf_name, value).should eq(value)
37
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
38
+ end
39
+
40
+ it "should properly convert integer values that fit into 1 byte" do
41
+ test_for_value(1)
42
+ end
43
+ it "should properly convert integer values that fit into 2 bytes" do
44
+ test_for_value(2**8 + 80)
45
+ end
46
+ it "should properly convert integer values that fit into 3 bytes" do
47
+ test_for_value(2**16 + 622)
48
+ end
49
+ it "should properly convert integer values that fit into 4 bytes" do
50
+ test_for_value(2**24 + 45820)
51
+ end
52
+ it "should properly convert integer values that fit into 5 bytes" do
53
+ test_for_value(2**32 + 618387)
54
+ end
55
+ end
56
+
57
+ context "with blob validation" do
58
+ let(:cf_name) { "validation_cf_blob" }
59
+ if CASSANDRA_VERSION.to_f == 0.8
60
+ before(:each) { create_column_family(cf_name, 'bytea') }
61
+ else
62
+ before(:each) { create_column_family(cf_name, 'blob') }
63
+ end
64
+
65
+ it "should return a blob" do
66
+ bytes = "binary\x00"
67
+ bytes = bytes.force_encoding('ASCII-8BIT') if RUBY_VERSION >= "1.9"
68
+ create_and_fetch_column(cf_name, bytes).should eq(bytes)
69
+ end
70
+ end
71
+
72
+ context "with boolean validation" do
73
+ let(:cf_name) { "validation_cf_boolean" }
74
+ before(:each) { create_column_family(cf_name, 'boolean') }
75
+
76
+ it "should return true" do
77
+ create_and_fetch_column(cf_name, true).should be_true
78
+ end
79
+
80
+ it "should return false" do
81
+ create_and_fetch_column(cf_name, false).should be_false
82
+ end
83
+ end
84
+
85
+ context "with counter validation" do
86
+ let(:cf_name) { "validation_cf_counter" }
87
+ before(:each) {
88
+ if !@connection.schema.column_family_names.include?(cf_name)
89
+ @connection.execute("CREATE COLUMNFAMILY #{cf_name} (id text PRIMARY KEY) WITH default_validation=CounterColumnType")
90
+ end
91
+ @connection.execute("TRUNCATE #{cf_name}")
92
+ }
93
+
94
+ it "should increment a few times" do
95
+ 10.times do |i|
96
+ @connection.execute("UPDATE #{cf_name} SET test=test + 1 WHERE id=?", 'test_key')
97
+ @connection.execute("SELECT test FROM #{cf_name} WHERE id=?", 'test_key').fetch[0].should eq(i+1)
98
+ end
99
+ end
100
+
101
+ it "should decrement a few times" do
102
+ 10.times do |i|
103
+ @connection.execute("UPDATE #{cf_name} SET test=test - 1 WHERE id=?", 'test_key')
104
+ @connection.execute("SELECT test FROM #{cf_name} WHERE id=?", 'test_key').fetch[0].should eq((i+1)*-1)
105
+ end
106
+ end
107
+ end
108
+
109
+ if CASSANDRA_VERSION.to_f >= 1.0
110
+ context "with decimal validation" do
111
+ let(:cf_name) { "validation_cf_decimal" }
112
+ before(:each) { create_column_family(cf_name, 'decimal') }
113
+
114
+ def test_for_value(value)
115
+ create_and_fetch_column(cf_name, value).should eq(value)
116
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
117
+ end
118
+
119
+ it "should return a small decimal" do
120
+ test_for_value(15.333)
121
+ end
122
+ it "should return a huge decimal" do
123
+ test_for_value(BigDecimal.new('129182739481237481341234123411.1029348102934810293481039'))
124
+ end
125
+ end
126
+ end
127
+
128
+ context "with double validation" do
129
+ let(:cf_name) { "validation_cf_double" }
130
+ before(:each) { create_column_family(cf_name, 'double') }
131
+
132
+ def test_for_value(value)
133
+ create_and_fetch_column(cf_name, value).should be_within(0.1).of(value)
134
+ create_and_fetch_column(cf_name, value*-1).should be_within(0.1).of(-1*value)
135
+ end
136
+
137
+ it "should properly convert some float values" do
138
+ test_for_value(1.125)
139
+ test_for_value(384.125)
140
+ test_for_value(65540.125)
141
+ test_for_value(16777217.125)
142
+ test_for_value(1099511627776.125)
143
+ end
144
+ end
145
+
146
+ context "with float validation" do
147
+ let(:cf_name) { "validation_cf_float" }
148
+ before(:each) { create_column_family(cf_name, 'float') }
149
+
150
+ def test_for_value(value)
151
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
152
+ create_and_fetch_column(cf_name, value).should eq(value)
153
+ end
154
+
155
+ it "should properly convert some float values" do
156
+ test_for_value(1.125)
157
+ test_for_value(384.125)
158
+ test_for_value(65540.125)
159
+ end
160
+ end
161
+
162
+ context "with int validation" do
163
+ let(:cf_name) { "validation_cf_int" }
164
+ before(:each) { create_column_family(cf_name, 'int') }
165
+
166
+ def test_for_value(value)
167
+ create_and_fetch_column(cf_name, value).should eq(value)
168
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
169
+ end
170
+
171
+ it "should properly convert integer values that fit into 1 byte" do
172
+ test_for_value(1)
173
+ end
174
+ it "should properly convert integer values that fit into 2 bytes" do
175
+ test_for_value(2**8 + 80)
176
+ end
177
+ it "should properly convert integer values that fit into 3 bytes" do
178
+ test_for_value(2**16 + 622)
179
+ end
180
+ it "should properly convert integer values that fit into 4 bytes" do
181
+ test_for_value(2**24 + 45820)
182
+ end
183
+ end
184
+
185
+ context "with text validation" do
186
+ let(:cf_name) { "validation_cf_text" }
187
+ before(:each) { create_column_family(cf_name, 'varchar') }
188
+
189
+ it "should return a non-multibyte string" do
190
+ create_and_fetch_column(cf_name, "snark").should eq("snark")
191
+ end
192
+
193
+ it "should return a multibyte string" do
194
+ if RUBY_VERSION >= "1.9"
195
+ create_and_fetch_column(cf_name, "sn\xC3\xA5rk".force_encoding('UTF-8')).should eq("sn\xC3\xA5rk".force_encoding('UTF-8'))
196
+ else
197
+ create_and_fetch_column(cf_name, "snårk").should eq("snårk")
198
+ end
199
+ end
200
+ end
201
+
202
+ context "with timestamp validation" do
203
+ let(:cf_name) { "validation_cf_timestamp" }
204
+ if CASSANDRA_VERSION.to_f == 0.8
205
+ before(:each) { create_column_family(cf_name, 'date') }
206
+ else
207
+ before(:each) { create_column_family(cf_name, 'timestamp') }
208
+ end
209
+
210
+ it "should return a timestamp" do
211
+ ts = Time.new
212
+ res = create_and_fetch_column(cf_name, ts)
213
+ res.to_f.should be_within(0.001).of(ts.to_f)
214
+ res.class.should eq(Time)
215
+ end
216
+
217
+ it "should return a timestamp given a date" do
218
+ date = Date.today
219
+ res = create_and_fetch_column(cf_name, date)
220
+ [:year, :month, :day].each do |sym|
221
+ res.send(sym).should eq(date.send(sym))
222
+ end
223
+ res.class.should eq(Time)
224
+ end
225
+ end
226
+
227
+ context "with uuid validation" do
228
+ let(:cf_name) { "validation_cf_uuid" }
229
+ before(:each) { create_column_family(cf_name, 'uuid') }
230
+
231
+ it "should return a uuid" do
232
+ uuid = UUID.new
233
+ create_and_fetch_column(cf_name, uuid).should eq(uuid)
234
+ end
235
+ end
236
+
237
+ context "with varchar validation" do
238
+ let(:cf_name) { "validation_cf_varchar" }
239
+ before(:each) { create_column_family(cf_name, 'varchar') }
240
+
241
+ it "should return a non-multibyte string" do
242
+ create_and_fetch_column(cf_name, "snark").should eq("snark")
243
+ end
244
+
245
+ it "should return a multibyte string" do
246
+ create_and_fetch_column(cf_name, "snårk").should eq("snårk")
247
+ end
248
+ end
249
+
250
+ context "with varint validation" do
251
+ let(:cf_name) { "validation_cf_varint" }
252
+ before(:each) { create_column_family(cf_name, 'varint') }
253
+
254
+ def test_for_value(value)
255
+ create_and_fetch_column(cf_name, value).should eq(value)
256
+ create_and_fetch_column(cf_name, value*-1).should eq(value*-1)
257
+ end
258
+
259
+ it "should properly convert integer values that fit into 1 byte" do
260
+ test_for_value(1)
261
+ end
262
+ it "should properly convert integer values that fit into 2 bytes" do
263
+ test_for_value(2**8 + 80)
264
+ end
265
+ it "should properly convert integer values that fit into 3 bytes" do
266
+ test_for_value(2**16 + 622)
267
+ end
268
+ it "should properly convert integer values that fit into more than 8 bytes" do
269
+ test_for_value(2**256)
270
+ end
271
+ end
272
+ end