couchbase 0.9.8 → 1.0.0

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 (51) hide show
  1. data/.gitignore +8 -0
  2. data/.yardopts +5 -0
  3. data/HISTORY.markdown +14 -10
  4. data/README.markdown +293 -98
  5. data/Rakefile +19 -24
  6. data/couchbase.gemspec +25 -7
  7. data/ext/couchbase_ext/couchbase_ext.c +2332 -0
  8. data/ext/couchbase_ext/extconf.rb +102 -0
  9. data/lib/couchbase.rb +20 -30
  10. data/lib/couchbase/bucket.rb +43 -112
  11. data/lib/couchbase/version.rb +3 -2
  12. data/tasks/benchmark.rake +6 -0
  13. data/tasks/compile.rake +52 -0
  14. data/tasks/doc.rake +27 -0
  15. data/tasks/test.rake +94 -0
  16. data/tasks/util.rake +21 -0
  17. data/test/profile/.gitignore +1 -0
  18. data/test/profile/Gemfile +6 -0
  19. data/test/profile/benchmark.rb +195 -0
  20. data/test/setup.rb +107 -18
  21. data/test/test_arithmetic.rb +98 -0
  22. data/test/test_async.rb +211 -0
  23. data/test/test_bucket.rb +126 -23
  24. data/test/test_cas.rb +59 -0
  25. data/test/test_couchbase.rb +22 -3
  26. data/test/test_delete.rb +63 -0
  27. data/test/test_errors.rb +82 -0
  28. data/test/test_flush.rb +49 -0
  29. data/test/test_format.rb +98 -0
  30. data/test/test_get.rb +236 -0
  31. data/test/test_stats.rb +53 -0
  32. data/test/test_store.rb +186 -0
  33. data/test/test_touch.rb +57 -0
  34. data/test/test_version.rb +17 -0
  35. metadata +72 -58
  36. data/lib/couchbase/couchdb.rb +0 -107
  37. data/lib/couchbase/document.rb +0 -71
  38. data/lib/couchbase/http_status.rb +0 -118
  39. data/lib/couchbase/latch.rb +0 -71
  40. data/lib/couchbase/memcached.rb +0 -372
  41. data/lib/couchbase/node.rb +0 -49
  42. data/lib/couchbase/rest_client.rb +0 -124
  43. data/lib/couchbase/view.rb +0 -182
  44. data/test/support/buckets-config.json +0 -843
  45. data/test/support/sample_design_doc.json +0 -9
  46. data/test/test_couchdb.rb +0 -98
  47. data/test/test_document.rb +0 -11
  48. data/test/test_latch.rb +0 -88
  49. data/test/test_memcached.rb +0 -59
  50. data/test/test_rest_client.rb +0 -14
  51. data/test/test_view.rb +0 -98
@@ -1,9 +0,0 @@
1
- {
2
- "_id": "_design/test_it_creates_design_doc_from_io",
3
- "language": "javascript",
4
- "views": {
5
- "all": {
6
- "map": "function(doc){ if(doc.msg){ emit(doc._id, doc.msg) } }"
7
- }
8
- }
9
- }
@@ -1,98 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
2
-
3
- class TestCouchdb < MiniTest::Unit::TestCase
4
- def setup
5
- @bucket = Couchbase.new('http://localhost:8091/pools/default')
6
- end
7
-
8
- def test_that_it_could_connect_to_couchdb
9
- server_uri = @bucket.next_node.couch_api_base[/http:\/\/[^\/]+/]
10
- assert_equal %w(couchbase couchdb version), @bucket.http_get(server_uri).keys.sort
11
- end
12
-
13
- def test_that_it_raises_error_if_couch_api_isnt_implemented
14
- bucket = Couchbase.new('http://localhost:8091/pools/default')
15
- bucket.nodes.each{|node| node.couch_api_base = nil}
16
- assert_raises(Couchbase::NotImplemented) do
17
- bucket.design_docs
18
- end
19
- end
20
-
21
- def test_that_it_could_create_doc_using_memcached_api
22
- # cleanup
23
- @bucket.delete(test_id) rescue Memcached::NotFound
24
- @bucket.delete_design_doc(test_id)
25
-
26
- @bucket[test_id] = {'msg' => 'hello world'}
27
- @bucket.save_design_doc('_id' => "_design/#{test_id}",
28
- 'views' => {'all' => {'map' => 'function(doc){if(doc.msg){emit(doc._id, doc.msg)}}'}})
29
- assert_operation_completed { database_ready(@bucket) }
30
- ddoc = @bucket.design_docs[test_id]
31
- assert ddoc, "design document '_design/#{test_id}' not found"
32
- doc = ddoc.all.detect{|doc| doc['id'] == test_id && doc['value'] == 'hello world'}
33
- assert doc, "object '#{test_id}' not found"
34
- end
35
-
36
- def test_that_it_could_remove_design_doc
37
- @bucket.delete_design_doc(test_id)
38
- @bucket[test_id] = {'msg' => 'hello world'}
39
- @bucket.save_design_doc('_id' => "_design/#{test_id}",
40
- 'views' => {'all' => {'map' => 'function(doc){if(doc.msg){emit(doc._id, doc.msg)}}'}})
41
- assert_operation_completed { database_ready(@bucket) }
42
- ddoc = @bucket.design_docs[test_id]
43
- assert ddoc, "design document '_design/#{test_id}' not found"
44
- @bucket.delete_design_doc("_design/#{test_id}")
45
- ddoc = @bucket.design_docs[test_id]
46
- refute ddoc, "design document '_design/#{test_id}' still here"
47
- end
48
-
49
- def test_it_creates_design_doc_from_string
50
- doc = <<-EOD
51
- {
52
- "_id": "_design/#{test_id}",
53
- "language": "javascript",
54
- "views": {
55
- "all": {
56
- "map": "function(doc){ if(doc.msg){ emit(doc._id, doc.msg) } }"
57
- }
58
- }
59
- }
60
- EOD
61
-
62
- @bucket.delete_design_doc(test_id)
63
- @bucket.save_design_doc(doc)
64
- assert_operation_completed { database_ready(@bucket) }
65
- assert @bucket.design_docs[test_id], "design document '_design/#{test_id}' not found"
66
- end
67
-
68
- def test_it_creates_design_doc_from_io
69
- doc = File.open(File.join(File.dirname(__FILE__), 'support', 'sample_design_doc.json'))
70
- @bucket.delete_design_doc(test_id)
71
- @bucket.save_design_doc(doc)
72
- assert_operation_completed { database_ready(@bucket) }
73
- assert @bucket.design_docs[test_id], "design document '_design/#{test_id}' not found"
74
- end
75
-
76
- def test_it_creates_design_doc_from_hash
77
- doc = {
78
- "_id" => "_design/#{test_id}",
79
- "language" => "javascript",
80
- "views" => {
81
- "all" => {
82
- "map" => "function(doc){ if(doc.msg){ emit(doc._id, doc.msg) } }"
83
- }
84
- }
85
- }
86
-
87
- @bucket.delete_design_doc(test_id)
88
- @bucket.save_design_doc(doc)
89
- assert_operation_completed { database_ready(@bucket) }
90
- assert @bucket.design_docs[test_id], "design document '_design/#{test_id}' not found"
91
- end
92
-
93
- protected
94
-
95
- def test_id
96
- name = caller.first[/.*[` ](.*)'/, 1]
97
- end
98
- end
@@ -1,11 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'couchbase'
3
-
4
- class TestView < MiniTest::Unit::TestCase
5
- def test_that_it_defines_views_for_design_documents_only
6
- design_doc = Couchbase::Document.new(:mock, {'_id' => '_design/foo', 'views' => {'all' => {'map' => 'function(doc){}'}}})
7
- assert_respond_to(design_doc, :all)
8
- regular_doc = Couchbase::Document.new(:mock, {'_id' => 'foo', 'views' => {'all' => {'map' => 'function(doc){}'}}})
9
- refute_respond_to(regular_doc, :all)
10
- end
11
- end
@@ -1,88 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
2
-
3
- class TestLatch < MiniTest::Unit::TestCase
4
- def test_properly_initialize
5
- l = Couchbase::Latch.new(true, false)
6
- assert_equal(true, l.state)
7
- assert_equal(false, l.target)
8
- end
9
-
10
- def test_basic_latch_usage
11
- latch = Couchbase::Latch.new(:dirty, :ready)
12
- obj = "bar"
13
- Thread.new do
14
- obj = "foo"
15
- latch.toggle
16
- end
17
- latch.wait
18
- assert_equal(:ready, latch.state)
19
- assert_equal("foo", obj)
20
- end
21
-
22
- def test_basic_latch_usage_inverted
23
- latch = Couchbase::Latch.new(:dirty, :ready)
24
- obj = "bar"
25
- Thread.new do
26
- latch.wait
27
- assert_equal(:ready, latch.state)
28
- assert_equal("foo", obj)
29
- end
30
- obj = "foo"
31
- latch.toggle
32
- end
33
-
34
- def test_latch_with_identical_values_skips_wait
35
- latch = Couchbase::Latch.new(:ready, :ready)
36
- latch.wait
37
- assert_equal(:ready, latch.state)
38
- end
39
-
40
- def test_toggle_with_two_chained_threads
41
- latch = Couchbase::Latch.new(:start, :end)
42
- name = "foo"
43
- Thread.new do
44
- Thread.new do
45
- name = "bar"
46
- latch.toggle
47
- end
48
- end
49
- latch.wait
50
- assert_equal(:end, latch.state)
51
- assert_equal("bar", name)
52
- end
53
-
54
- def test_toggle_with_multiple_waiters
55
- proceed_latch = Couchbase::Latch.new(:start, :end)
56
- result = :bar
57
- Thread.new do
58
- proceed_latch.wait
59
- assert_equal(:foo, result)
60
- end
61
- Thread.new do
62
- proceed_latch.wait
63
- assert_equal(:foo, result)
64
- end
65
- assert_equal(:bar, result)
66
- proceed_latch.toggle
67
- assert_equal(:end, proceed_latch.state)
68
- end
69
-
70
- def test_interleaved_latches
71
- check_latch = Couchbase::Latch.new(:dirty, :ready)
72
- change_1_latch = Couchbase::Latch.new(:dirty, :ready)
73
- change_2_latch = Couchbase::Latch.new(:dirty, :ready)
74
- name = "foo"
75
- Thread.new do
76
- name = "bar"
77
- change_1_latch.toggle
78
- check_latch.wait
79
- name = "man"
80
- change_2_latch.toggle
81
- end
82
- change_1_latch.wait
83
- assert_equal("bar", name)
84
- check_latch.toggle
85
- change_2_latch.wait
86
- assert_equal("man", name)
87
- end
88
- end
@@ -1,59 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
2
-
3
- class TestMemcached < MiniTest::Unit::TestCase
4
-
5
- def test_race_absence_during_initialization
6
- session = connect
7
- assert_raises(Memcached::NotFound) do
8
- session.get(test_id)
9
- end
10
- end
11
-
12
- def test_experimental_features_is_always_on
13
- assert_respond_to connect, :touch
14
- assert_respond_to connect(:experimental_features => false), :touch
15
- assert_respond_to connect('experimental_features' => false), :touch
16
- end
17
-
18
- def test_single_get
19
- session = connect
20
- session.set(test_id, "foo")
21
- assert "foo", session.get(test_id)
22
- end
23
-
24
- def test_single_get_missing
25
- assert_raises(Memcached::NotFound) do
26
- connect.get("missing-key")
27
- end
28
- end
29
-
30
- def test_multi_get
31
- session = connect
32
- session.set(test_id(1), "foo")
33
- session.set(test_id(2), "bar")
34
- expected = {test_id(1) => "foo", test_id(2) => "bar"}
35
- assert expected, session.get(test_id(1), test_id(2))
36
- ids = [1, 2].map{|n| test_id(n)}
37
- assert expected, session.get(ids)
38
- end
39
-
40
- def test_multi_get_missing
41
- session = connect
42
- session.set(test_id(1), "foo")
43
- expected = {test_id(1) => "foo"}
44
- assert expected, session.get(test_id(1), test_id(2))
45
- ids = [1, 2].map{|n| test_id(n)}
46
- assert expected, session.get(ids)
47
- end
48
-
49
- protected
50
-
51
- def connect(options = {})
52
- uri = options.delete(:pool_uri) || "http://localhost:8091/pools/default"
53
- Couchbase.new(uri, options)
54
- end
55
-
56
- def test_id(suffix = nil)
57
- "#{caller.first[/.*[` ](.*)'/, 1]}#{suffix}"
58
- end
59
- end
@@ -1,14 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'couchbase'
3
-
4
- class TestRestClient < MiniTest::Unit::TestCase
5
- class RestClientMock
6
- extend Couchbase::RestClient
7
- end
8
-
9
- def test_that_build_uri_duplicates_string
10
- uri = "http://example.com/"
11
- assert_equal "http://example.com/?foo=bar", RestClientMock.send(:build_query, uri, {'foo' => 'bar'})
12
- assert_equal "http://example.com/", uri
13
- end
14
- end
@@ -1,98 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'setup')
2
-
3
- class TestView < MiniTest::Unit::TestCase
4
- def test_pagination
5
- connection = populate_database
6
- view = connection.design_docs['test_view'].all
7
-
8
- # fetch all records
9
- collection = view.fetch(:limit => 10)
10
- assert_equal 10, collection.size
11
- assert_equal 100, collection.total_entries
12
-
13
- # fetch with reduce
14
- view = connection.design_docs['test_view'].sum
15
- docs = view.fetch(:limit => 2, :group => true)
16
- assert_equal 2, docs.size
17
- assert_equal nil, docs.total_entries
18
-
19
- assert_instance_of Couchbase::View, connection.all_docs
20
- end
21
-
22
- def test_when_stream_has_errors_it_raises_error_by_default
23
- response = <<-EOR
24
- {
25
- "total_rows": 0,
26
- "rows": [ ],
27
- "errors": [
28
- {
29
- "from": "127.0.0.1:5984",
30
- "reason": "Design document `_design/testfoobar` missing in database `test_db_b`."
31
- },
32
- {
33
- "from": "http:// localhost:5984/_view_merge/",
34
- "reason": "Design document `_design/testfoobar` missing in database `test_db_c`."
35
- }
36
- ]
37
- }
38
- EOR
39
- view = Couchbase::View.new(stub(:curl_easy => response),
40
- "http://localhost:5984/default/_design/test/_view/all")
41
- assert_raises(Couchbase::ViewError) do
42
- view.fetch
43
- end
44
- end
45
-
46
- def test_when_stream_has_errors_and_error_callback_provided_it_executes_the_callback
47
- response = <<-EOR
48
- {
49
- "total_rows": 0,
50
- "rows": [ ],
51
- "errors": [
52
- {
53
- "from": "127.0.0.1:5984",
54
- "reason": "Design document `_design/testfoobar` missing in database `test_db_b`."
55
- },
56
- {
57
- "from": "http:// localhost:5984/_view_merge/",
58
- "reason": "Design document `_design/testfoobar` missing in database `test_db_c`."
59
- }
60
- ]
61
- }
62
- EOR
63
- view = Couchbase::View.new(stub(:curl_easy => response),
64
- "http://localhost:5984/default/_design/test/_view/all")
65
- errcount = 0
66
- view.on_error{|from, reason| errcount += 1}
67
- view.fetch
68
- assert 2, errcount
69
- end
70
-
71
- protected
72
-
73
- def populate_database
74
- connection = Couchbase.new('http://localhost:8091/pools/default')
75
- # clear storage
76
- connection.flush
77
- # save 100 documents
78
- toys = %w(buzz rex bo hamm slink potato)
79
- 100.times do |t|
80
- connection["test_view_#{t}"]= {:counter => t+1, :toy => toys[t%6]}
81
- end
82
-
83
- connection.delete_design_doc('test_view')
84
- connection.save_design_doc('_id' => '_design/test_view',
85
- 'views' => {
86
- 'all' => {'map' => 'function(doc){if(doc.counter){emit(doc._id, doc)}}'},
87
- 'sum' => {'map' => 'function(doc){if(doc.counter){emit(doc.toy, doc.counter)}}',
88
- 'reduce' => 'function(keys,values,rereduce){return sum(values)}'}})
89
-
90
- assert connection.design_docs['test_view']
91
-
92
- assert_operation_completed do
93
- database_ready(connection) && connection.all_docs.count > 100
94
- end
95
- connection
96
- end
97
-
98
- end