cassilds 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/CHANGELOG +53 -0
  2. data/LICENSE +202 -0
  3. data/Manifest +45 -0
  4. data/README.rdoc +83 -0
  5. data/Rakefile +9 -0
  6. data/bin/cassandra_helper +16 -0
  7. data/cassandra.gemspec +46 -0
  8. data/conf/cassandra.in.sh +47 -0
  9. data/conf/cassandra.yaml +113 -0
  10. data/conf/log4j.properties +38 -0
  11. data/conf/storage-conf.xml +342 -0
  12. data/lib/cassandra/0.6/cassandra.rb +68 -0
  13. data/lib/cassandra/0.6/columns.rb +35 -0
  14. data/lib/cassandra/0.6/protocol.rb +92 -0
  15. data/lib/cassandra/0.6.rb +7 -0
  16. data/lib/cassandra/0.7/cassandra.rb +272 -0
  17. data/lib/cassandra/0.7/column_family.rb +3 -0
  18. data/lib/cassandra/0.7/columns.rb +67 -0
  19. data/lib/cassandra/0.7/keyspace.rb +3 -0
  20. data/lib/cassandra/0.7/protocol.rb +139 -0
  21. data/lib/cassandra/0.7.rb +7 -0
  22. data/lib/cassandra/array.rb +8 -0
  23. data/lib/cassandra/cassandra.rb +302 -0
  24. data/lib/cassandra/columns.rb +79 -0
  25. data/lib/cassandra/comparable.rb +28 -0
  26. data/lib/cassandra/constants.rb +11 -0
  27. data/lib/cassandra/debug.rb +9 -0
  28. data/lib/cassandra/helpers.rb +40 -0
  29. data/lib/cassandra/long.rb +58 -0
  30. data/lib/cassandra/mock.rb +326 -0
  31. data/lib/cassandra/ordered_hash.rb +200 -0
  32. data/lib/cassandra/time.rb +11 -0
  33. data/lib/cassandra.rb +39 -0
  34. data/test/cassandra_client_test.rb +20 -0
  35. data/test/cassandra_mock_test.rb +73 -0
  36. data/test/cassandra_test.rb +412 -0
  37. data/test/comparable_types_test.rb +45 -0
  38. data/test/eventmachine_test.rb +42 -0
  39. data/test/ordered_hash_test.rb +380 -0
  40. data/test/test_helper.rb +14 -0
  41. data/vendor/0.6/gen-rb/cassandra.rb +1481 -0
  42. data/vendor/0.6/gen-rb/cassandra_constants.rb +12 -0
  43. data/vendor/0.6/gen-rb/cassandra_types.rb +482 -0
  44. data/vendor/0.7/gen-rb/cassandra.rb +1937 -0
  45. data/vendor/0.7/gen-rb/cassandra_constants.rb +12 -0
  46. data/vendor/0.7/gen-rb/cassandra_types.rb +679 -0
  47. metadata +176 -0
@@ -0,0 +1,326 @@
1
+ require 'nokogiri'
2
+
3
+ class SimpleUUID::UUID
4
+ def >=(other)
5
+ (self <=> other) >= 0
6
+ end
7
+
8
+ def <=(other)
9
+ (self <=> other) <= 0
10
+ end
11
+ end
12
+
13
+ class Cassandra
14
+ class Mock
15
+ include ::Cassandra::Helpers
16
+ include ::Cassandra::Columns
17
+
18
+ def initialize(keyspace, storage_xml)
19
+ @keyspace = keyspace
20
+ @column_name_class = {}
21
+ @sub_column_name_class = {}
22
+ @storage_xml = storage_xml
23
+ clear_keyspace!
24
+ end
25
+
26
+ def disconnect!
27
+ end
28
+
29
+ def clear_keyspace!
30
+ @data = {}
31
+ end
32
+
33
+ def clear_column_family!(column_family)
34
+ @data[column_family.to_sym] = OrderedHash.new
35
+ end
36
+
37
+ def insert(column_family, key, hash_or_array, options = {})
38
+ if @batch
39
+ @batch << [:insert, column_family, key, hash_or_array, options]
40
+ else
41
+ raise ArgumentError if key.nil?
42
+ if column_family_type(column_family) == 'Standard'
43
+ insert_standard(column_family, key, hash_or_array)
44
+ else
45
+ insert_super(column_family, key, hash_or_array)
46
+ end
47
+ end
48
+ end
49
+
50
+ def insert_standard(column_family, key, hash_or_array)
51
+ old = cf(column_family)[key] || OrderedHash.new
52
+ cf(column_family)[key] = merge_and_sort(old, hash_or_array)
53
+ end
54
+
55
+ def insert_super(column_family, key, hash)
56
+ raise ArgumentError unless hash.is_a?(Hash)
57
+ cf(column_family)[key] ||= OrderedHash.new
58
+
59
+ hash.keys.each do |sub_key|
60
+ old = cf(column_family)[key][sub_key] || OrderedHash.new
61
+ cf(column_family)[key][sub_key] = merge_and_sort(old, hash[sub_key])
62
+ end
63
+ end
64
+
65
+ def batch
66
+ @batch = []
67
+ yield
68
+ b = @batch
69
+ @batch = nil
70
+ b.each do |mutation|
71
+ send(*mutation)
72
+ end
73
+ ensure
74
+ @batch = nil
75
+ end
76
+
77
+ def get(column_family, key, *columns_and_options)
78
+ column_family, column, sub_column, options =
79
+ extract_and_validate_params_for_real(column_family, [key], columns_and_options, READ_DEFAULTS)
80
+ if column_family_type(column_family) == 'Standard'
81
+ get_standard(column_family, key, column, options)
82
+ else
83
+ get_super(column_family, key, column, sub_column, options)
84
+ end
85
+ end
86
+
87
+ def get_standard(column_family, key, column, options)
88
+ row = cf(column_family)[key] || OrderedHash.new
89
+ if column
90
+ row[column]
91
+ else
92
+ row = apply_range(row, column_family, options[:start], options[:finish])
93
+ apply_count(row, options[:count], options[:reversed])
94
+ end
95
+ end
96
+
97
+ def get_super(column_family, key, column, sub_column, options)
98
+ if column
99
+ if sub_column
100
+ if cf(column_family)[key] &&
101
+ cf(column_family)[key][column] &&
102
+ cf(column_family)[key][column][sub_column]
103
+ cf(column_family)[key][column][sub_column]
104
+ else
105
+ nil
106
+ end
107
+ else
108
+ row = cf(column_family)[key] && cf(column_family)[key][column] ?
109
+ cf(column_family)[key][column] :
110
+ OrderedHash.new
111
+ row = apply_range(row, column_family, options[:start], options[:finish], false)
112
+ apply_count(row, options[:count], options[:reversed])
113
+ end
114
+ elsif cf(column_family)[key]
115
+ cf(column_family)[key]
116
+ else
117
+ OrderedHash.new
118
+ end
119
+ end
120
+
121
+ def exists?(column_family, key, column=nil)
122
+ !!get(column_family, key, column)
123
+ end
124
+
125
+ def multi_get(column_family, keys, *columns_and_options)
126
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, keys, columns_and_options, READ_DEFAULTS)
127
+ keys.inject(OrderedHash.new) do |hash, key|
128
+ hash[key] = get(column_family, key)
129
+ hash
130
+ end
131
+ end
132
+
133
+ def remove(column_family, key, *columns_and_options)
134
+ column_family, column, sub_column, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, WRITE_DEFAULTS)
135
+ if @batch
136
+ @batch << [:remove, column_family, key, column]
137
+ else
138
+ if column
139
+ if sub_column
140
+ cf(column_family)[key][column].delete(sub_column)
141
+ else
142
+ cf(column_family)[key].delete(column)
143
+ end
144
+ else
145
+ cf(column_family).delete(key)
146
+ end
147
+ end
148
+ end
149
+
150
+ def get_columns(column_family, key, *columns_and_options)
151
+ column_family, columns, sub_columns, options = extract_and_validate_params_for_real(column_family, key, columns_and_options, READ_DEFAULTS)
152
+ d = get(column_family, key)
153
+
154
+
155
+ if sub_columns
156
+ sub_columns.collect do |sub_column|
157
+ d[columns][sub_column]
158
+ end
159
+ else
160
+ columns.collect do |column|
161
+ d[column]
162
+ end
163
+ end
164
+ end
165
+
166
+ def count_columns(column_family, key, column=nil)
167
+ get(column_family, key, column).keys.length
168
+ end
169
+
170
+ def multi_get_columns(column_family, keys, columns)
171
+ keys.inject(OrderedHash.new) do |hash, key|
172
+ hash[key] = get_columns(column_family, key, columns)
173
+ hash
174
+ end
175
+ end
176
+
177
+ def multi_count_columns(column_family, keys)
178
+ keys.inject(OrderedHash.new) do |hash, key|
179
+ hash[key] = count_columns(column_family, key)
180
+ hash
181
+ end
182
+ end
183
+
184
+ def get_range(column_family, options = {})
185
+ column_family, _, _, options = extract_and_validate_params_for_real(column_family, "", [options], READ_DEFAULTS)
186
+ _get_range(column_family, options[:start], options[:finish], options[:count]).keys
187
+ end
188
+
189
+ def count_range(column_family, options={})
190
+ count = 0
191
+ l = []
192
+ start_key = ''
193
+ while (l = get_range(column_family, options.merge(:count => 1000, :start => start_key))).size > 0
194
+ count += l.size
195
+ start_key = l.last.succ
196
+ end
197
+ count
198
+ end
199
+
200
+ def schema(load=true)
201
+ if !load && !@schema
202
+ []
203
+ else
204
+ @schema ||= schema_for_keyspace(@keyspace)
205
+ end
206
+ end
207
+
208
+ private
209
+
210
+ def _get_range(column_family, start, finish, count)
211
+ ret = OrderedHash.new
212
+ start = to_compare_with_type(start, column_family)
213
+ finish = to_compare_with_type(finish, column_family)
214
+ cf(column_family).keys.sort.each do |key|
215
+ break if ret.keys.size >= count
216
+ if (start.nil? || key >= start) && (finish.nil? || key <= finish)
217
+ ret[key] = cf(column_family)[key]
218
+ end
219
+ end
220
+ ret
221
+ end
222
+
223
+ def schema_for_keyspace(keyspace)
224
+ doc = read_storage_xml
225
+ ret = {}
226
+ doc.css("Keyspaces Keyspace[@Name='#{keyspace}']").css('ColumnFamily').each do |cf|
227
+ ret[cf['Name']] = {}
228
+ if cf['CompareSubcolumnsWith']
229
+ ret[cf['Name']]['CompareSubcolumnsWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareSubcolumnsWith']
230
+ end
231
+ if cf['CompareWith']
232
+ ret[cf['Name']]['CompareWith'] = 'org.apache.cassandra.db.marshal.' + cf['CompareWith']
233
+ end
234
+ if cf['ColumnType'] == 'Super'
235
+ ret[cf['Name']]['Type'] = 'Super'
236
+ else
237
+ ret[cf['Name']]['Type'] = 'Standard'
238
+ end
239
+ end
240
+ ret
241
+ end
242
+
243
+ def read_storage_xml
244
+ @doc ||= Nokogiri::XML(open(@storage_xml))
245
+ end
246
+
247
+ def extract_and_validate_params_for_real(column_family, keys, args, options)
248
+ column_family, columns, sub_column, options = extract_and_validate_params(column_family, keys, args, options)
249
+ options[:start] = nil if options[:start] == ''
250
+ options[:finish] = nil if options[:finish] == ''
251
+ [column_family, to_compare_with_types(columns, column_family), to_compare_with_types(sub_column, column_family, false), options]
252
+ end
253
+
254
+ def to_compare_with_types(column_names, column_family, standard=true)
255
+ if column_names.is_a?(Array)
256
+ column_names.collect do |name|
257
+ to_compare_with_type(name, column_family, standard)
258
+ end
259
+ else
260
+ to_compare_with_type(column_names, column_family, standard)
261
+ end
262
+ end
263
+
264
+ def to_compare_with_type(column_name, column_family, standard=true)
265
+ return column_name if column_name.nil?
266
+ klass = if standard
267
+ schema[column_family.to_s]["CompareWith"]
268
+ else
269
+ schema[column_family.to_s]["CompareSubcolumnsWith"]
270
+ end
271
+
272
+ case klass
273
+ when "org.apache.cassandra.db.marshal.UTF8Type", "org.apache.cassandra.db.marshal.BytesType"
274
+ column_name
275
+ when "org.apache.cassandra.db.marshal.TimeUUIDType"
276
+ SimpleUUID::UUID.new(column_name)
277
+ when "org.apache.cassandra.db.marshal.LongType"
278
+ Long.new(column_name)
279
+ else
280
+ raise "Unknown column family type: #{klass.inspect}"
281
+ end
282
+ end
283
+
284
+ def column_family_type(column_family)
285
+ schema[column_family.to_s]['Type']
286
+ end
287
+
288
+ def cf(column_family)
289
+ @data[column_family.to_sym] ||= OrderedHash.new
290
+ end
291
+
292
+ def merge_and_sort(old_stuff, new_stuff)
293
+ if new_stuff.is_a?(Array)
294
+ new_stuff = new_stuff.inject({}){|h,k| h[k] = nil; h }
295
+ end
296
+ OrderedHash[old_stuff.merge(new_stuff).sort{|a,b| a[0] <=> b[0]}]
297
+ end
298
+
299
+ def apply_count(row, count, reversed=false)
300
+ if count
301
+ keys = row.keys.sort
302
+ keys = keys.reverse if reversed
303
+ keys = keys[0...count]
304
+ keys.inject(OrderedHash.new) do |memo, key|
305
+ memo[key] = row[key]
306
+ memo
307
+ end
308
+ else
309
+ row
310
+ end
311
+ end
312
+
313
+ def apply_range(row, column_family, strt, fin, standard=true)
314
+ start = to_compare_with_type(strt, column_family, standard)
315
+ finish = to_compare_with_type(fin, column_family, standard)
316
+ ret = OrderedHash.new
317
+ row.keys.each do |key|
318
+ if (start.nil? || key >= start) && (finish.nil? || key <= finish)
319
+ ret[key] = row[key]
320
+ end
321
+ end
322
+ ret
323
+ end
324
+
325
+ end
326
+ end
@@ -0,0 +1,200 @@
1
+ # OrderedHash is namespaced to prevent conflicts with other implementations
2
+ class Cassandra
3
+ # Hash is ordered in Ruby 1.9!
4
+ if RUBY_VERSION >= '1.9'
5
+ OrderedHashInt = ::Hash
6
+ else
7
+ class OrderedHashInt < Hash #:nodoc:
8
+ def initialize(*args, &block)
9
+ super
10
+ @keys = []
11
+ end
12
+
13
+ def self.[](*args)
14
+ ordered_hash = new
15
+
16
+ if (args.length == 1 && args.first.is_a?(Array))
17
+ args.first.each do |key_value_pair|
18
+ next unless (key_value_pair.is_a?(Array))
19
+ ordered_hash[key_value_pair[0]] = key_value_pair[1]
20
+ end
21
+
22
+ return ordered_hash
23
+ end
24
+
25
+ unless (args.size % 2 == 0)
26
+ raise ArgumentError.new("odd number of arguments for Hash")
27
+ end
28
+
29
+ args.each_with_index do |val, ind|
30
+ next if (ind % 2 != 0)
31
+ ordered_hash[val] = args[ind + 1]
32
+ end
33
+
34
+ ordered_hash
35
+ end
36
+
37
+ def initialize_copy(other)
38
+ super
39
+ # make a deep copy of keys
40
+ @keys = other.keys
41
+ end
42
+
43
+ def []=(key, value)
44
+ @keys << key if !has_key?(key)
45
+ super
46
+ end
47
+
48
+ def delete(key)
49
+ if has_key? key
50
+ index = @keys.index(key)
51
+ @keys.delete_at index
52
+ end
53
+ super
54
+ end
55
+
56
+ def delete_if
57
+ super
58
+ sync_keys!
59
+ self
60
+ end
61
+
62
+ def reject!
63
+ super
64
+ sync_keys!
65
+ self
66
+ end
67
+
68
+ def reject(&block)
69
+ dup.reject!(&block)
70
+ end
71
+
72
+ def keys
73
+ @keys.dup
74
+ end
75
+
76
+ def values
77
+ @keys.collect { |key| self[key] }
78
+ end
79
+
80
+ def to_hash
81
+ self
82
+ end
83
+
84
+ def to_a
85
+ @keys.map { |key| [ key, self[key] ] }
86
+ end
87
+
88
+ def each_key
89
+ @keys.each { |key| yield key }
90
+ end
91
+
92
+ def each_value
93
+ @keys.each { |key| yield self[key]}
94
+ end
95
+
96
+ def each
97
+ @keys.each {|key| yield [key, self[key]]}
98
+ end
99
+
100
+ alias_method :each_pair, :each
101
+
102
+ def clear
103
+ super
104
+ @keys.clear
105
+ self
106
+ end
107
+
108
+ def shift
109
+ k = @keys.first
110
+ v = delete(k)
111
+ [k, v]
112
+ end
113
+
114
+ def merge!(other_hash)
115
+ other_hash.each {|k,v| self[k] = v }
116
+ self
117
+ end
118
+
119
+ def merge(other_hash)
120
+ dup.merge!(other_hash)
121
+ end
122
+
123
+ # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
124
+ def replace(other)
125
+ super
126
+ @keys = other.keys
127
+ self
128
+ end
129
+
130
+ private
131
+
132
+ def sync_keys!
133
+ @keys.delete_if {|k| !has_key?(k)}
134
+ end
135
+ end
136
+ end
137
+
138
+ class OrderedHash < OrderedHashInt #:nodoc:
139
+ def initialize(*args, &block)
140
+ @timestamps = Hash.new
141
+ super
142
+ end
143
+
144
+ def initialize_copy(other)
145
+ @timestamps = other.timestamps
146
+ super
147
+ end
148
+
149
+ def []=(key, value, timestamp = nil)
150
+ @timestamps[key] = timestamp
151
+ super(key, value)
152
+ end
153
+
154
+ def delete(key)
155
+ @timestamps.delete(key)
156
+ super
157
+ end
158
+
159
+ def delete_if
160
+ @timestamps.delete_if
161
+ super
162
+ end
163
+
164
+ def reject!
165
+ @timestamps.reject!
166
+ super
167
+ end
168
+
169
+ def timestamps
170
+ @timestamps.dup
171
+ end
172
+
173
+ def clear
174
+ @timestamps.clear
175
+ super
176
+ end
177
+
178
+ def shift
179
+ k, v = super
180
+ @timestamps.delete(k)
181
+ [k, v]
182
+ end
183
+
184
+ def replace(other)
185
+ @timestamps = other.timestamps
186
+ super
187
+ end
188
+
189
+ def inspect
190
+ "#<OrderedHash #{super}--TimeStamps: #{@timestamps.inspect}>"
191
+ end
192
+
193
+ private
194
+
195
+ def sync_keys!
196
+ @timestamps.delete_if {|k,v| !has_key?(k)}
197
+ super
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,11 @@
1
+
2
+ class Time
3
+ def self.stamp
4
+ Time.now.utc.stamp
5
+ end
6
+
7
+ def stamp
8
+ to_i * 1_000_000 + usec
9
+ end
10
+ end
11
+
data/lib/cassandra.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ gem 'thrift', '~> 0.5.0'
3
+ require 'thrift'
4
+ gem 'thrift_client', '~> 0.6.0'
5
+ require 'thrift_client'
6
+ gem 'simple_uuid' , '~> 0.1.0'
7
+ require 'simple_uuid'
8
+
9
+ require 'json' unless defined?(JSON)
10
+
11
+ here = File.expand_path(File.dirname(__FILE__))
12
+
13
+ class Cassandra ; end
14
+ unless Cassandra.respond_to?(:VERSION)
15
+ require "#{here}/cassandra/0.7"
16
+ end
17
+
18
+ $LOAD_PATH << "#{here}/../vendor/#{Cassandra.VERSION}/gen-rb"
19
+ require "#{here}/../vendor/#{Cassandra.VERSION}/gen-rb/cassandra"
20
+
21
+ $LOAD_PATH << "#{here}"
22
+
23
+ require 'cassandra/helpers'
24
+ require 'cassandra/array'
25
+ require 'cassandra/time'
26
+ require 'cassandra/comparable'
27
+ require 'cassandra/long'
28
+ require 'cassandra/ordered_hash'
29
+ require 'cassandra/columns'
30
+ require "cassandra/#{Cassandra.VERSION}/columns"
31
+ require "cassandra/#{Cassandra.VERSION}/protocol"
32
+ require "cassandra/cassandra"
33
+ require "cassandra/#{Cassandra.VERSION}/cassandra"
34
+ unless Cassandra.VERSION.eql?("0.6")
35
+ require "cassandra/#{Cassandra.VERSION}/column_family"
36
+ require "cassandra/#{Cassandra.VERSION}/keyspace"
37
+ end
38
+ require 'cassandra/constants'
39
+ require 'cassandra/debug' if ENV['DEBUG']
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class CassandraClientTest < Test::Unit::TestCase
4
+ include Cassandra::Constants
5
+
6
+ def setup
7
+ @twitter = Cassandra.new('Twitter', "127.0.0.1:9160", :retries => 2, :exception_classes => [])
8
+ end
9
+
10
+ def test_client_method_is_called
11
+ assert_nil @twitter.instance_variable_get(:@client)
12
+ @twitter.insert(:Statuses, key, {'1' => 'v', '2' => 'v', '3' => 'v'})
13
+ assert_not_nil @twitter.instance_variable_get(:@client)
14
+ end
15
+
16
+ def key
17
+ caller.first[/`(.*?)'/, 1]
18
+ end
19
+
20
+ end
@@ -0,0 +1,73 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+ require 'cassandra_test'
3
+ require 'cassandra/mock'
4
+
5
+ class CassandraMockTest < CassandraTest
6
+ include Cassandra::Constants
7
+
8
+ def setup
9
+ storage_xml_path = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), 'conf', 'storage-conf.xml'))
10
+ @twitter = Cassandra::Mock.new('Twitter', storage_xml_path)
11
+ @twitter.clear_keyspace!
12
+
13
+ @blogs = Cassandra::Mock.new('Multiblog', storage_xml_path)
14
+ @blogs.clear_keyspace!
15
+
16
+ @blogs_long = Cassandra::Mock.new('MultiblogLong', storage_xml_path)
17
+ @blogs_long.clear_keyspace!
18
+
19
+ @uuids = (0..6).map {|i| SimpleUUID::UUID.new(Time.at(2**(24+i))) }
20
+ @longs = (0..6).map {|i| Long.new(Time.at(2**(24+i))) }
21
+ end
22
+
23
+ def test_setup
24
+ assert @twitter
25
+ assert @blogs
26
+ assert @blogs_long
27
+ end
28
+
29
+ def test_schema_for_keyspace
30
+ data = {
31
+ "StatusRelationships"=>{
32
+ "CompareSubcolumnsWith"=>"org.apache.cassandra.db.marshal.TimeUUIDType",
33
+ "CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
34
+ "Type"=>"Super"},
35
+ "StatusAudits"=>{
36
+ "CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
37
+ "Type"=>"Standard"},
38
+ "Statuses"=>{
39
+ "CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
40
+ "Type"=>"Standard"},
41
+ "UserRelationships"=>{
42
+ "CompareSubcolumnsWith"=>"org.apache.cassandra.db.marshal.TimeUUIDType",
43
+ "CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
44
+ "Type"=>"Super"},
45
+ "UserAudits"=>{
46
+ "CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type",
47
+ "Type"=>"Standard"},
48
+ "Users"=>{"CompareWith"=>"org.apache.cassandra.db.marshal.UTF8Type", "Type"=>"Standard"},
49
+ "TimelinishThings"=>
50
+ {"CompareWith"=>"org.apache.cassandra.db.marshal.BytesType", "Type"=>"Standard"}
51
+ }
52
+ stuff = @twitter.send(:schema_for_keyspace, 'Twitter')
53
+ data.keys.each do |k|
54
+ assert_equal data[k], stuff[k], k
55
+ end
56
+ end
57
+
58
+ def test_sorting_row_keys
59
+ @twitter.insert(:Statuses, 'b', {:text => 'foo'})
60
+ @twitter.insert(:Statuses, 'a', {:text => 'foo'})
61
+ assert_equal ['a'], @twitter.get_range(:Statuses, :count => 1)
62
+ end
63
+
64
+ def test_inserting_array_for_indices
65
+ @twitter.insert(:TimelinishThings, 'a', ['1','2'])
66
+ row = @twitter.get(:TimelinishThings, 'a')
67
+ assert_equal({'1' => nil, '2' => nil}, row)
68
+
69
+ assert_raises(ArgumentError) {
70
+ @twitter.insert(:UserRelationships, 'a', ['u1','u2'])
71
+ }
72
+ end
73
+ end