├── vendor
└── sinatra
│ ├── test
│ ├── views
│ │ ├── hello.test
│ │ ├── layout2.test
│ │ ├── hello.erb
│ │ ├── hello.haml
│ │ ├── error.sass
│ │ ├── foo
│ │ │ └── hello.test
│ │ ├── layout2.erb
│ │ ├── layout2.haml
│ │ ├── hello.sass
│ │ ├── hello.builder
│ │ ├── error.builder
│ │ ├── layout2.builder
│ │ ├── error.haml
│ │ └── error.erb
│ ├── data
│ │ └── reload_app_file.rb
│ ├── sinatra_test.rb
│ ├── server_test.rb
│ ├── request_test.rb
│ ├── response_test.rb
│ ├── route_added_hook_test.rb
│ ├── builder_test.rb
│ ├── contest.rb
│ ├── helper.rb
│ ├── middleware_test.rb
│ ├── erb_test.rb
│ ├── result_test.rb
│ ├── haml_test.rb
│ ├── filter_test.rb
│ ├── sass_test.rb
│ ├── static_test.rb
│ └── extensions_test.rb
│ ├── lib
│ ├── sinatra
│ │ ├── images
│ │ │ ├── 404.png
│ │ │ └── 500.png
│ │ └── main.rb
│ └── sinatra.rb
│ ├── .gitignore
│ ├── LICENSE
│ ├── AUTHORS
│ └── sinatra.gemspec
├── public
└── _utils
│ ├── favicon.ico
│ ├── image
│ ├── bg.png
│ ├── add.png
│ ├── apply.gif
│ ├── hgrad.gif
│ ├── load.png
│ ├── logo.png
│ ├── path.gif
│ ├── run.png
│ ├── save.png
│ ├── thead.gif
│ ├── cancel.gif
│ ├── compact.png
│ ├── delete.png
│ ├── grippie.gif
│ ├── rarrow.png
│ ├── running.png
│ ├── spinner.gif
│ ├── twisty.gif
│ ├── order-asc.gif
│ ├── order-desc.gif
│ ├── progress.gif
│ ├── run-mini.png
│ ├── thead-key.gif
│ ├── delete-mini.png
│ ├── test_failure.gif
│ ├── test_success.gif
│ ├── sidebar-toggle.png
│ ├── toggle-collapse.gif
│ └── toggle-expand.gif
│ ├── dialog
│ ├── _delete_document.html
│ ├── _delete_database.html
│ ├── _compact_database.html
│ ├── _create_database.html
│ ├── _upload_attachment.html
│ └── _save_view_as.html
│ ├── script
│ ├── test
│ │ ├── form_submit.js
│ │ ├── large_docs.js
│ │ ├── recreate_doc.js
│ │ ├── view_multi_key_temp.js
│ │ ├── content_negotiation.js
│ │ ├── view_xml.js
│ │ ├── utf8.js
│ │ ├── reduce_false.js
│ │ ├── view_conflicts.js
│ │ ├── copy_doc.js
│ │ ├── compact.js
│ │ ├── http.js
│ │ ├── view_multi_key_all_docs.js
│ │ ├── view_sandboxing.js
│ │ ├── batch_save.js
│ │ ├── lots_of_docs.js
│ │ ├── conflicts.js
│ │ ├── jsonp.js
│ │ ├── config.js
│ │ ├── design_options.js
│ │ ├── etags_head.js
│ │ ├── design_paths.js
│ │ ├── invalid_docids.js
│ │ ├── attachment_views.js
│ │ ├── multiple_rows.js
│ │ ├── attachment_names.js
│ │ ├── all_docs.js
│ │ ├── purge.js
│ │ ├── rev_stemming.js
│ │ ├── bulk_docs.js
│ │ ├── etags_views.js
│ │ ├── view_offsets.js
│ │ ├── erlang_views.js
│ │ └── uuids.js
│ ├── jquery.cookies.js
│ ├── jquery.resizer.js
│ ├── jquery.dialog.js
│ └── jquery.editinline.js
│ ├── _sidebar.html
│ ├── couch_tests.html
│ ├── index.html
│ ├── status.html
│ ├── custom_test.html
│ └── config.html
├── spec
├── spec_helper.rb
├── document_spec.rb
├── view_spec.rb
├── database_spec.rb
└── tree_spec.rb
├── lib
├── httpd
│ ├── views.rb
│ ├── global.rb
│ ├── db.rb
│ └── doc.rb
├── query
│ ├── server
│ │ ├── validate.js
│ │ ├── filter.js
│ │ ├── state.js
│ │ ├── loop.js
│ │ └── util.js
│ └── query_server.rb
├── booth.rb
└── store
│ ├── database.rb
│ └── tree.rb
└── README.md
/vendor/sinatra/test/views/hello.test:
--------------------------------------------------------------------------------
1 | Hello World!
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/layout2.test:
--------------------------------------------------------------------------------
1 | Layout 2!
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/hello.erb:
--------------------------------------------------------------------------------
1 | Hello <%= 'World' %>
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/hello.haml:
--------------------------------------------------------------------------------
1 | %h1 Hello From Haml
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/error.sass:
--------------------------------------------------------------------------------
1 | #sass
2 | +argle-bargle
3 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/foo/hello.test:
--------------------------------------------------------------------------------
1 | from another views directory
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/layout2.erb:
--------------------------------------------------------------------------------
1 | ERB Layout!
2 | <%= yield %>
3 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/layout2.haml:
--------------------------------------------------------------------------------
1 | %h1 HAML Layout!
2 | %p= yield
3 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/hello.sass:
--------------------------------------------------------------------------------
1 | #sass
2 | :background-color #FFF
3 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/hello.builder:
--------------------------------------------------------------------------------
1 | xml.exclaim "You're my boy, #{@name}!"
2 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/error.builder:
--------------------------------------------------------------------------------
1 | xml.error do
2 | raise "goodbye"
3 | end
4 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/layout2.builder:
--------------------------------------------------------------------------------
1 | xml.layout do
2 | xml << yield
3 | end
4 |
--------------------------------------------------------------------------------
/public/_utils/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/favicon.ico
--------------------------------------------------------------------------------
/public/_utils/image/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/bg.png
--------------------------------------------------------------------------------
/public/_utils/image/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/add.png
--------------------------------------------------------------------------------
/public/_utils/image/apply.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/apply.gif
--------------------------------------------------------------------------------
/public/_utils/image/hgrad.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/hgrad.gif
--------------------------------------------------------------------------------
/public/_utils/image/load.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/load.png
--------------------------------------------------------------------------------
/public/_utils/image/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/logo.png
--------------------------------------------------------------------------------
/public/_utils/image/path.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/path.gif
--------------------------------------------------------------------------------
/public/_utils/image/run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/run.png
--------------------------------------------------------------------------------
/public/_utils/image/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/save.png
--------------------------------------------------------------------------------
/public/_utils/image/thead.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/thead.gif
--------------------------------------------------------------------------------
/public/_utils/image/cancel.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/cancel.gif
--------------------------------------------------------------------------------
/public/_utils/image/compact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/compact.png
--------------------------------------------------------------------------------
/public/_utils/image/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/delete.png
--------------------------------------------------------------------------------
/public/_utils/image/grippie.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/grippie.gif
--------------------------------------------------------------------------------
/public/_utils/image/rarrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/rarrow.png
--------------------------------------------------------------------------------
/public/_utils/image/running.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/running.png
--------------------------------------------------------------------------------
/public/_utils/image/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/spinner.gif
--------------------------------------------------------------------------------
/public/_utils/image/twisty.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/twisty.gif
--------------------------------------------------------------------------------
/public/_utils/image/order-asc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/order-asc.gif
--------------------------------------------------------------------------------
/public/_utils/image/order-desc.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/order-desc.gif
--------------------------------------------------------------------------------
/public/_utils/image/progress.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/progress.gif
--------------------------------------------------------------------------------
/public/_utils/image/run-mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/run-mini.png
--------------------------------------------------------------------------------
/public/_utils/image/thead-key.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/thead-key.gif
--------------------------------------------------------------------------------
/public/_utils/image/delete-mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/delete-mini.png
--------------------------------------------------------------------------------
/public/_utils/image/test_failure.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/test_failure.gif
--------------------------------------------------------------------------------
/public/_utils/image/test_success.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/test_success.gif
--------------------------------------------------------------------------------
/public/_utils/image/sidebar-toggle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/sidebar-toggle.png
--------------------------------------------------------------------------------
/public/_utils/image/toggle-collapse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/toggle-collapse.gif
--------------------------------------------------------------------------------
/public/_utils/image/toggle-expand.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/public/_utils/image/toggle-expand.gif
--------------------------------------------------------------------------------
/vendor/sinatra/test/data/reload_app_file.rb:
--------------------------------------------------------------------------------
1 | $reload_count += 1
2 |
3 | $reload_app.get('/') { 'Hello from reload file' }
4 |
--------------------------------------------------------------------------------
/vendor/sinatra/lib/sinatra/images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/vendor/sinatra/lib/sinatra/images/404.png
--------------------------------------------------------------------------------
/vendor/sinatra/lib/sinatra/images/500.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jchris/booth/master/vendor/sinatra/lib/sinatra/images/500.png
--------------------------------------------------------------------------------
/vendor/sinatra/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .DS_Store
3 | /pkg
4 | /book
5 | /doc/api
6 | /doc/*.html
7 | .#*
8 | \#*
9 | .emacs*
10 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/error.haml:
--------------------------------------------------------------------------------
1 | %h1 Hello From Haml
2 | = raise 'goodbye' unless defined?(french) && french
3 | = raise 'au revoir' if defined?(french) && french
4 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/views/error.erb:
--------------------------------------------------------------------------------
1 | Hello <%= 'World' %>
2 | <% raise 'Goodbye' unless defined?(french) && french %>
3 | <% raise 'Au revoir' if defined?(french) && french %>
4 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require "rubygems"
2 | require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
3 |
4 | require File.join(File.expand_path(File.dirname(__FILE__)),"..","lib","booth")
5 |
6 |
--------------------------------------------------------------------------------
/vendor/sinatra/lib/sinatra.rb:
--------------------------------------------------------------------------------
1 | libdir = File.dirname(__FILE__)
2 | $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3 |
4 | require 'sinatra/base'
5 | require 'sinatra/main'
6 |
7 | use_in_file_templates!
8 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/sinatra_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class SinatraTest < Test::Unit::TestCase
4 | it 'creates a new Sinatra::Base subclass on new' do
5 | app =
6 | Sinatra.new do
7 | get '/' do
8 | 'Hello World'
9 | end
10 | end
11 | assert_same Sinatra::Base, app.superclass
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/httpd/views.rb:
--------------------------------------------------------------------------------
1 | require 'view'
2 |
3 | # handle temp views
4 | post "/:db/_temp_view/?" do
5 | with_db(params[:db]) do |db|
6 | req = JSON.parse(request.body.read)
7 | v = View.new(db, req["map"], req["reduce"])
8 | j(200, v.query(View.view_params(params)))
9 | end
10 | end
11 |
12 | # ddoc views should be similar,
13 | # just keep a ref to the view around
14 | # so we can update it.
15 |
--------------------------------------------------------------------------------
/lib/query/server/validate.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | var Validate = {
14 | validate : function(funSrc, newDoc, oldDoc, userCtx) {
15 | var validateFun = compileFunction(funSrc);
16 | try {
17 | validateFun(newDoc, oldDoc, userCtx);
18 | print("1");
19 | } catch (error) {
20 | respond(error);
21 | }
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/vendor/sinatra/lib/sinatra/main.rb:
--------------------------------------------------------------------------------
1 | require 'sinatra/base'
2 |
3 | module Sinatra
4 | class Application < Base
5 |
6 | # we assume that the first file that requires 'sinatra' is the
7 | # app_file. all other path related options are calculated based
8 | # on this path by default.
9 | set :app_file, caller_files.first || $0
10 |
11 | set :run, Proc.new { $0 == app_file }
12 |
13 | if run? && ARGV.any?
14 | require 'optparse'
15 | OptionParser.new { |op|
16 | op.on('-x') { set :lock, true }
17 | op.on('-e env') { |val| set :environment, val.to_sym }
18 | op.on('-s server') { |val| set :server, val }
19 | op.on('-p port') { |val| set :port, val.to_i }
20 | }.parse!(ARGV.dup)
21 | end
22 |
23 | at_exit do
24 | raise $! if $!
25 | run! if run?
26 | end
27 | end
28 | end
29 |
30 | include Sinatra::Delegator
31 |
--------------------------------------------------------------------------------
/lib/query/server/filter.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | var Filter = {
14 | filter : function(docs, req, userCtx) {
15 | var results = [];
16 | try {
17 | for (var i=0; i < docs.length; i++) {
18 | results.push((funs[0](docs[i], req, userCtx) && true) || false);
19 | };
20 | respond([true, results]);
21 | } catch (error) {
22 | respond(error);
23 | }
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_delete_document.html:
--------------------------------------------------------------------------------
1 |
15 |
27 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_delete_database.html:
--------------------------------------------------------------------------------
1 |
15 |
28 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_compact_database.html:
--------------------------------------------------------------------------------
1 |
15 |
29 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/server_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | module Rack::Handler
4 | class Mock
5 | extend Test::Unit::Assertions
6 |
7 | def self.run(app, options={})
8 | assert(app < Sinatra::Base)
9 | assert_equal 9001, options[:Port]
10 | assert_equal 'foo.local', options[:Host]
11 | yield new
12 | end
13 |
14 | def stop
15 | end
16 | end
17 |
18 | register 'mock', 'Rack::Handler::Mock'
19 | end
20 |
21 | class ServerTest < Test::Unit::TestCase
22 | setup do
23 | mock_app {
24 | set :server, 'mock'
25 | set :host, 'foo.local'
26 | set :port, 9001
27 | }
28 | $stdout = File.open('/dev/null', 'wb')
29 | end
30 |
31 | def teardown
32 | $stdout = STDOUT
33 | end
34 |
35 | it "locates the appropriate Rack handler and calls ::run" do
36 | @app.run!
37 | end
38 |
39 | it "sets options on the app before running" do
40 | @app.run! :sessions => true
41 | assert @app.sessions?
42 | end
43 |
44 | it "falls back on the next server handler when not found" do
45 | @app.run! :server => %w[foo bar mock]
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/vendor/sinatra/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2007, 2008, 2009 Blake Mizerany
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/public/_utils/script/test/form_submit.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | // Do some basic tests.
14 | couchTests.form_submit = function(debug) {
15 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
16 | db.deleteDb();
17 | db.createDb();
18 |
19 | // PUT on existing DB should return 412 instead of 500
20 | var json = "{}";
21 | var xhr = CouchDB.request("POST", "/test_suite_db/baz", {body: json});
22 | T(xhr.status == 415);
23 | result = JSON.parse(xhr.responseText);
24 | T(result.error, "bad_content_type");
25 | T(result.reason, "Invalid Content-Type header for form upload");
26 | };
27 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/request_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class RequestTest < Test::Unit::TestCase
4 | it 'responds to #user_agent' do
5 | request = Sinatra::Request.new({'HTTP_USER_AGENT' => 'Test'})
6 | assert request.respond_to?(:user_agent)
7 | assert_equal 'Test', request.user_agent
8 | end
9 |
10 | it 'parses POST params when Content-Type is form-dataish' do
11 | request = Sinatra::Request.new(
12 | 'REQUEST_METHOD' => 'PUT',
13 | 'CONTENT_TYPE' => 'application/x-www-form-urlencoded',
14 | 'rack.input' => StringIO.new('foo=bar')
15 | )
16 | assert_equal 'bar', request.params['foo']
17 | end
18 |
19 | it 'is secure when the url scheme is https' do
20 | request = Sinatra::Request.new('rack.url_scheme' => 'https')
21 | assert request.secure?
22 | end
23 |
24 | it 'is not secure when the url scheme is http' do
25 | request = Sinatra::Request.new('rack.url_scheme' => 'http')
26 | assert !request.secure?
27 | end
28 |
29 | it 'respects X-Forwarded-Proto header for proxied SSL' do
30 | request = Sinatra::Request.new('HTTP_X_FORWARDED_PROTO' => 'https')
31 | assert request.secure?
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/public/_utils/script/test/large_docs.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.large_docs = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var longtext = "0123456789\n";
20 |
21 | for (var i=0; i<10; i++) {
22 | longtext = longtext + longtext
23 | }
24 | T(db.save({"longtest":longtext}).ok);
25 | T(db.save({"longtest":longtext}).ok);
26 | T(db.save({"longtest":longtext}).ok);
27 | T(db.save({"longtest":longtext}).ok);
28 |
29 | // query all documents, and return the doc.foo member as a key.
30 | results = db.query(function(doc){
31 | emit(null, doc.longtest);
32 | });
33 | };
34 |
--------------------------------------------------------------------------------
/lib/query/server/state.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | // globals used by other modules and functions
14 | var funs = []; // holds functions used for computation
15 | var funsrc = []; // holds function source for debug info
16 | var query_config = {};
17 | var State = (function() {
18 | return {
19 | reset : function(config) {
20 | // clear the globals and run gc
21 | funs = [];
22 | funsrc = [];
23 | query_config = config;
24 | gc();
25 | print("true"); // indicates success
26 | },
27 | addFun : function(newFun) {
28 | // Compile to a function and add it to funs array
29 | funsrc.push(newFun);
30 | funs.push(compileFunction(newFun));
31 | print("true");
32 | }
33 | }
34 | })();
35 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_create_database.html:
--------------------------------------------------------------------------------
1 |
15 |
34 |
--------------------------------------------------------------------------------
/public/_utils/script/test/recreate_doc.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.recreate_doc = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // First create a new document with the ID "foo", and delete it again
20 | var doc = {_id: "foo", a: "bar", b: 42};
21 | T(db.save(doc).ok);
22 | T(db.deleteDoc(doc).ok);
23 |
24 | // Now create a new document with the same ID, save it, and then modify it
25 | // This should work fine, but currently results in a conflict error, at
26 | // least "sometimes"
27 | for (var i = 0; i < 10; i++) {
28 | doc = {_id: "foo"};
29 | T(db.save(doc).ok);
30 | doc = db.open("foo");
31 | doc.a = "baz";
32 | T(db.save(doc).ok);
33 | T(db.deleteDoc(doc).rev != undefined);
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/response_test.rb:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | require File.dirname(__FILE__) + '/helper'
4 |
5 | class ResponseTest < Test::Unit::TestCase
6 | setup do
7 | @response = Sinatra::Response.new
8 | end
9 |
10 | it "initializes with 200, text/html, and empty body" do
11 | assert_equal 200, @response.status
12 | assert_equal 'text/html', @response['Content-Type']
13 | assert_equal [], @response.body
14 | end
15 |
16 | it 'uses case insensitive headers' do
17 | @response['content-type'] = 'application/foo'
18 | assert_equal 'application/foo', @response['Content-Type']
19 | assert_equal 'application/foo', @response['CONTENT-TYPE']
20 | end
21 |
22 | it 'writes to body' do
23 | @response.body = 'Hello'
24 | @response.write ' World'
25 | assert_equal 'Hello World', @response.body
26 | end
27 |
28 | [204, 304].each do |status_code|
29 | it "removes the Content-Type header and body when response status is #{status_code}" do
30 | @response.status = status_code
31 | @response.body = ['Hello World']
32 | assert_equal [status_code, {}, []], @response.finish
33 | end
34 | end
35 |
36 | it 'Calculates the Content-Length using the bytesize of the body' do
37 | @response.body = ['Hello', 'World!', '✈']
38 | status, headers, body = @response.finish
39 | assert_equal '14', headers['Content-Length']
40 | assert_equal @response.body, body
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/public/_utils/_sidebar.html:
--------------------------------------------------------------------------------
1 |
15 |
37 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_upload_attachment.html:
--------------------------------------------------------------------------------
1 |
15 |
37 |
--------------------------------------------------------------------------------
/public/_utils/script/test/view_multi_key_temp.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.view_multi_key_temp = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var docs = makeDocs(0, 100);
20 | db.bulkSave(docs);
21 |
22 | var queryFun = function(doc) { emit(doc.integer, doc.integer) };
23 | var reduceFun = function (keys, values) { return sum(values); };
24 |
25 | var keys = [10,15,30,37,50];
26 | var rows = db.query(queryFun, null, {}, keys).rows;
27 | for(var i=0; iTesting XML"});
20 | db.save({content: "Testing E4X"});
21 |
22 | var results = db.query(
23 | "function(doc) {\n" +
24 | " var xml = new XML(doc.content);\n" +
25 | " emit(xml.title.text(), null);\n" +
26 | "}");
27 | T(results.total_rows == 2);
28 | T(results.rows[0].key == "Testing E4X");
29 | T(results.rows[1].key == "Testing XML");
30 |
31 | var results = db.query(
32 | "function(doc) {\n" +
33 | " var xml = new XML(doc.content);\n" +
34 | " emit(xml.title.@id, null);\n" +
35 | "}");
36 | T(results.total_rows == 2);
37 | T(results.rows[0].key == "e4x");
38 | T(results.rows[1].key == "xml");
39 | };
40 |
--------------------------------------------------------------------------------
/public/_utils/dialog/_save_view_as.html:
--------------------------------------------------------------------------------
1 |
15 |
36 |
--------------------------------------------------------------------------------
/public/_utils/script/test/utf8.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.utf8 = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var texts = [];
20 |
21 | texts[0] = "1. Ascii: hello"
22 | texts[1] = "2. Russian: На берегу пустынных волн"
23 | texts[2] = "3. Math: ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i),"
24 | texts[3] = "4. Geek: STARGΛ̊TE SG-1"
25 | texts[4] = "5. Braille: ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌"
26 |
27 | // check that we can save a reload with full fidelity
28 | for (var i=0; i @error, "reason" => @reason})
38 | end
39 | end
40 |
41 | BOOTH_UUID = UUID.new
42 |
43 |
44 | # TODO Help! I want code reloading during dev.
45 |
46 | set :public, File.join(filepath,"..","public")
47 | set :show_exceptions, false
48 | set :raise_errors, false
49 | set :lock, false
50 |
51 | error(BoothError) do
52 | be = @env['sinatra.error']
53 | [be.code, {}, be.to_json]
54 | end
55 |
56 | error(Sinatra::NotFound) do
57 | [404, {}, {"error"=>"not_found", "reason" => "missing handler"}.to_json]
58 | end
59 |
60 | error ::Exception do
61 | be = @env['sinatra.error']
62 | [500,{}, {"error"=>"internal_error", "reason" => be.to_s}.to_json]
63 | end
64 |
65 | load 'global.rb'
66 | load 'db.rb'
67 | load 'doc.rb'
68 | load 'views.rb'
69 |
70 |
--------------------------------------------------------------------------------
/public/_utils/script/test/reduce_false.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.reduce_false = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var numDocs = 5;
20 | var docs = makeDocs(1,numDocs + 1);
21 | db.bulkSave(docs);
22 | var summate = function(N) {return (N+1)*N/2;};
23 |
24 | var designDoc = {
25 | _id:"_design/test",
26 | language: "javascript",
27 | views: {
28 | summate: {map:"function (doc) {emit(doc.integer, doc.integer)};",
29 | reduce:"function (keys, values) { return sum(values); };"},
30 | }
31 | };
32 | T(db.save(designDoc).ok);
33 |
34 | // Test that the reduce works
35 | var res = db.view('test/summate');
36 | T(res.rows.length == 1 && res.rows[0].value == summate(5));
37 |
38 | //Test that we get our docs back
39 | res = db.view('test/summate', {reduce: false});
40 | T(res.rows.length == 5);
41 | for(var i=0; i<5; i++)
42 | {
43 | T(res.rows[i].value == i+1);
44 | }
45 | };
46 |
--------------------------------------------------------------------------------
/lib/httpd/global.rb:
--------------------------------------------------------------------------------
1 | # render couchdb's classic JSON welcome screen
2 | # this is where redirect to other servers would go
3 | get '/' do
4 | j 200, "couchdb"=>"Welcome","version"=>"0"
5 | end
6 |
7 | # just a stub for the tests, as booth is in-memory only
8 | post '/:db/_ensure_full_commit' do
9 | j 200, "ok" => true
10 | end
11 |
12 | # also stubs
13 | post '/_restart' do
14 | j 200, "ok" => true
15 | end
16 | put '/_config/*' do
17 | j 200, "ok" => true
18 | end
19 | get '/_config/*' do
20 | j 200, "ok" => true
21 | end
22 |
23 |
24 | # the uuid service works just like couchdb
25 | get "/_uuids" do
26 | uuid = BOOTH_UUID
27 | count = if params[:count]
28 | params[:count].to_i
29 | else
30 | 1
31 | end
32 | uuids = (1..count).collect{uuid.generate}
33 | j(200, {"uuids" => uuids},{
34 | "Cache-Control" => "no-cache",
35 | "Pragma" => "no-cache",
36 | "Etag" => uuid.generate
37 | })
38 | end
39 |
40 |
41 | # json error handling
42 | def je code, name, message
43 | j code, {"error" => name, "reason" => message}
44 | end
45 |
46 | # json ok handling
47 | def j code, json, h = {}
48 | status code
49 | content_type "json"
50 | headers h
51 | json.to_json
52 | end
53 |
54 | def changes rows
55 | status 200
56 | content_type "json"
57 | "{\"results\":[\n#{change_rows(rows)}],\n\"last_seq\":#{rows.length}}\n"
58 | end
59 |
60 | def change_rows rows
61 | b = ""
62 | rows.each do |r|
63 | b = b + "#{r.to_json},\n"
64 | end
65 | b
66 | end
67 |
68 | # parse request
69 | def jbody message = "Request body must be a JSON object"
70 | json = JSON.parse(request.body.read)
71 | if !json || json.is_a?(Array)
72 | raise BoothError.new(400, "bad_request", message);
73 | end
74 | json
75 | end
--------------------------------------------------------------------------------
/public/_utils/script/test/view_conflicts.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.view_conflicts = function(debug) {
14 | var dbA = new CouchDB("test_suite_db_a", {"X-Couch-Full-Commit":"false"});
15 | dbA.deleteDb();
16 | dbA.createDb();
17 | var dbB = new CouchDB("test_suite_db_b", {"X-Couch-Full-Commit":"false"});
18 | dbB.deleteDb();
19 | dbB.createDb();
20 | if (debug) debugger;
21 |
22 | var docA = {_id: "foo", bar: 42};
23 | T(dbA.save(docA).ok);
24 | CouchDB.replicate(dbA.name, dbB.name);
25 |
26 | var docB = dbB.open("foo");
27 | docB.bar = 43;
28 | dbB.save(docB);
29 | docA.bar = 41;
30 | dbA.save(docA);
31 | CouchDB.replicate(dbA.name, dbB.name);
32 |
33 | var doc = dbB.open("foo", {conflicts: true});
34 | T(doc._conflicts.length == 1);
35 | var conflictRev = doc._conflicts[0];
36 | if (doc.bar == 41) { // A won
37 | T(conflictRev == docB._rev);
38 | } else { // B won
39 | T(doc.bar == 43);
40 | T(conflictRev == docA._rev);
41 | }
42 |
43 | var results = dbB.query(function(doc) {
44 | if (doc._conflicts) {
45 | emit(doc._id, doc._conflicts);
46 | }
47 | });
48 | T(results.rows[0].value[0] == conflictRev);
49 | };
50 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/builder_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 | require 'builder'
3 |
4 | class BuilderTest < Test::Unit::TestCase
5 | def builder_app(&block)
6 | mock_app {
7 | set :views, File.dirname(__FILE__) + '/views'
8 | get '/', &block
9 | }
10 | get '/'
11 | end
12 |
13 | it 'renders inline Builder strings' do
14 | builder_app { builder 'xml.instruct!' }
15 | assert ok?
16 | assert_equal %{\n}, body
17 | end
18 |
19 | it 'renders inline blocks' do
20 | builder_app {
21 | @name = "Frank & Mary"
22 | builder do |xml|
23 | xml.couple @name
24 | end
25 | }
26 | assert ok?
27 | assert_equal "Frank & Mary\n", body
28 | end
29 |
30 | it 'renders .builder files in views path' do
31 | builder_app {
32 | @name = "Blue"
33 | builder :hello
34 | }
35 | assert ok?
36 | assert_equal %(You're my boy, Blue!\n), body
37 | end
38 |
39 | it "renders with inline layouts" do
40 | mock_app {
41 | layout do
42 | %(xml.layout { xml << yield })
43 | end
44 | get('/') { builder %(xml.em 'Hello World') }
45 | }
46 | get '/'
47 | assert ok?
48 | assert_equal "\nHello World\n\n", body
49 | end
50 |
51 | it "renders with file layouts" do
52 | builder_app {
53 | builder %(xml.em 'Hello World'), :layout => :layout2
54 | }
55 | assert ok?
56 | assert_equal "\nHello World\n\n", body
57 | end
58 |
59 | it "raises error if template not found" do
60 | mock_app {
61 | get('/') { builder :no_such_template }
62 | }
63 | assert_raise(Errno::ENOENT) { get('/') }
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/public/_utils/script/jquery.cookies.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | (function($) {
14 | $.cookies = $.cookies || {}
15 | $.extend($.cookies, {
16 |
17 | /* Return the value of a cookie. */
18 | get: function(name, defaultValue) {
19 | var nameEq = name + "=";
20 | var parts = document.cookie.split(';');
21 | for (var i = 0; i < parts.length; i++) {
22 | var part = parts[i].replace(/^\s+/, "");
23 | if (part.indexOf(nameEq) == 0) {
24 | return unescape(part.substring(nameEq.length, part.length));
25 | }
26 | }
27 | return defaultValue !== undefined ? defaultValue : null;
28 | },
29 |
30 | /* Create or update a cookie. */
31 | set: function(name, value, path, days) {
32 | var params = [];
33 | if (path) {
34 | params.push("; path=" + path);
35 | }
36 | if (days) {
37 | var date = new Date();
38 | date.setTime(date.getTime() + (days * 24*60*60*1000));
39 | params.push("; expires=" + date.toGMTString());
40 | }
41 | document.cookie = name + "=" + escape(value) + params.join();
42 | },
43 |
44 | /* Remove a cookie. */
45 | remove: function(name, path) {
46 | $.cookies.set(name, "", path, -1);
47 | }
48 |
49 | });
50 | })(jQuery);
51 |
--------------------------------------------------------------------------------
/public/_utils/script/test/copy_doc.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.copy_doc = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // copy a doc
20 | T(db.save({_id:"doc_to_be_copied",v:1}).ok);
21 | var xhr = CouchDB.request("COPY", "/test_suite_db/doc_to_be_copied", {
22 | headers: {"Destination":"doc_that_was_copied"}
23 | });
24 |
25 | T(xhr.status == 201);
26 | T(db.open("doc_that_was_copied").v == 1);
27 |
28 | // COPY with existing target
29 | T(db.save({_id:"doc_to_be_copied2",v:1}).ok);
30 | var doc = db.save({_id:"doc_to_be_overwritten",v:2});
31 | T(doc.ok);
32 |
33 | // error condition
34 | var xhr = CouchDB.request("COPY", "/test_suite_db/doc_to_be_copied2", {
35 | headers: {"Destination":"doc_to_be_overwritten"}
36 | });
37 | T(xhr.status == 409); // conflict
38 |
39 | var rev = db.open("doc_to_be_overwritten")._rev;
40 | var xhr = CouchDB.request("COPY", "/test_suite_db/doc_to_be_copied2", {
41 | headers: {"Destination":"doc_to_be_overwritten?rev=" + rev}
42 | });
43 | T(xhr.status == 201);
44 |
45 | var over = db.open("doc_to_be_overwritten");
46 | T(rev != over._rev);
47 | T(over.v == 1);
48 | };
49 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/contest.rb:
--------------------------------------------------------------------------------
1 | require "test/unit"
2 |
3 | # Test::Unit loads a default test if the suite is empty, and the only
4 | # purpose of that test is to fail. As having empty contexts is a common
5 | # practice, we decided to overwrite TestSuite#empty? in order to
6 | # allow them. Having a failure when no tests have been defined seems
7 | # counter-intuitive.
8 | class Test::Unit::TestSuite
9 | unless method_defined?(:empty?)
10 | def empty?
11 | false
12 | end
13 | end
14 | end
15 |
16 | # We added setup, test and context as class methods, and the instance
17 | # method setup now iterates on the setup blocks. Note that all setup
18 | # blocks must be defined with the block syntax. Adding a setup instance
19 | # method defeats the purpose of this library.
20 | class Test::Unit::TestCase
21 | def self.setup(&block)
22 | setup_blocks << block
23 | end
24 |
25 | def setup
26 | self.class.setup_blocks.each do |block|
27 | instance_eval(&block)
28 | end
29 | end
30 |
31 | def self.context(name, &block)
32 | subclass = Class.new(self.superclass)
33 | subclass.setup_blocks.unshift(*setup_blocks)
34 | subclass.class_eval(&block)
35 | const_set(context_name(name), subclass)
36 | end
37 |
38 | def self.test(name, &block)
39 | define_method(test_name(name), &block)
40 | end
41 |
42 | class << self
43 | alias_method :should, :test
44 | alias_method :describe, :context
45 | end
46 |
47 | private
48 |
49 | def self.setup_blocks
50 | @setup_blocks ||= []
51 | end
52 |
53 | def self.context_name(name)
54 | "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
55 | end
56 |
57 | def self.test_name(name)
58 | "test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
59 | end
60 |
61 | def self.sanitize_name(name)
62 | name.gsub(/\W+/, ' ').strip
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/public/_utils/script/test/compact.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.compact = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 | var docs = makeDocs(0, 20);
19 | db.bulkSave(docs);
20 |
21 | var binAttDoc = {
22 | _id: "bin_doc",
23 | _attachments:{
24 | "foo.txt": {
25 | content_type:"text/plain",
26 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
27 | }
28 | }
29 | }
30 |
31 | T(db.save(binAttDoc).ok);
32 |
33 | var originalsize = db.info().disk_size;
34 |
35 | for(var i in docs) {
36 | db.deleteDoc(docs[i]);
37 | }
38 | T(db.ensureFullCommit().ok);
39 | var deletesize = db.info().disk_size;
40 | T(deletesize > originalsize);
41 |
42 | T(db.compact().ok);
43 | T(db.last_req.status == 202);
44 | // compaction isn't instantaneous, loop until done
45 | while (db.info().compact_running) {};
46 |
47 | T(db.ensureFullCommit().ok);
48 | restartServer();
49 | var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo.txt");
50 | T(xhr.responseText == "This is a base64 encoded text")
51 | T(xhr.getResponseHeader("Content-Type") == "text/plain")
52 | T(db.info().doc_count == 1);
53 | T(db.info().disk_size < deletesize);
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/helper.rb:
--------------------------------------------------------------------------------
1 | ENV['RACK_ENV'] = 'test'
2 |
3 | begin
4 | require 'rack'
5 | rescue LoadError
6 | require 'rubygems'
7 | require 'rack'
8 | end
9 |
10 | testdir = File.dirname(__FILE__)
11 | $LOAD_PATH.unshift testdir unless $LOAD_PATH.include?(testdir)
12 |
13 | libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
14 | $LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
15 |
16 | require 'contest'
17 | require 'rack/test'
18 | require 'sinatra/base'
19 |
20 | class Sinatra::Base
21 | # Allow assertions in request context
22 | include Test::Unit::Assertions
23 | end
24 |
25 | Sinatra::Base.set :environment, :test
26 |
27 | class Test::Unit::TestCase
28 | include Rack::Test::Methods
29 |
30 | class << self
31 | alias_method :it, :test
32 | end
33 |
34 | alias_method :response, :last_response
35 |
36 | setup do
37 | Sinatra::Base.set :environment, :test
38 | end
39 |
40 | # Sets up a Sinatra::Base subclass defined with the block
41 | # given. Used in setup or individual spec methods to establish
42 | # the application.
43 | def mock_app(base=Sinatra::Base, &block)
44 | @app = Sinatra.new(base, &block)
45 | end
46 |
47 | def app
48 | Rack::Lint.new(@app)
49 | end
50 |
51 | def body
52 | response.body.to_s
53 | end
54 |
55 | # Delegate other missing methods to response.
56 | def method_missing(name, *args, &block)
57 | if response && response.respond_to?(name)
58 | response.send(name, *args, &block)
59 | else
60 | super
61 | end
62 | end
63 |
64 | # Also check response since we delegate there.
65 | def respond_to?(symbol, include_private=false)
66 | super || (response && response.respond_to?(symbol, include_private))
67 | end
68 |
69 | # Do not output warnings for the duration of the block.
70 | def silence_warnings
71 | $VERBOSE, v = nil, $VERBOSE
72 | yield
73 | ensure
74 | $VERBOSE = v
75 | end
76 | end
77 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/middleware_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class MiddlewareTest < Test::Unit::TestCase
4 | setup do
5 | @app = mock_app(Sinatra::Default) {
6 | get '/*' do
7 | response.headers['X-Tests'] = env['test.ran'].
8 | map { |n| n.split('::').last }.
9 | join(', ')
10 | env['PATH_INFO']
11 | end
12 | }
13 | end
14 |
15 | class MockMiddleware < Struct.new(:app)
16 | def call(env)
17 | (env['test.ran'] ||= []) << self.class.to_s
18 | app.call(env)
19 | end
20 | end
21 |
22 | class UpcaseMiddleware < MockMiddleware
23 | def call(env)
24 | env['PATH_INFO'] = env['PATH_INFO'].upcase
25 | super
26 | end
27 | end
28 |
29 | it "is added with Sinatra::Application.use" do
30 | @app.use UpcaseMiddleware
31 | get '/hello-world'
32 | assert ok?
33 | assert_equal '/HELLO-WORLD', body
34 | end
35 |
36 | class DowncaseMiddleware < MockMiddleware
37 | def call(env)
38 | env['PATH_INFO'] = env['PATH_INFO'].downcase
39 | super
40 | end
41 | end
42 |
43 | it "runs in the order defined" do
44 | @app.use UpcaseMiddleware
45 | @app.use DowncaseMiddleware
46 | get '/Foo'
47 | assert_equal "/foo", body
48 | assert_equal "UpcaseMiddleware, DowncaseMiddleware", response['X-Tests']
49 | end
50 |
51 | it "resets the prebuilt pipeline when new middleware is added" do
52 | @app.use UpcaseMiddleware
53 | get '/Foo'
54 | assert_equal "/FOO", body
55 | @app.use DowncaseMiddleware
56 | get '/Foo'
57 | assert_equal '/foo', body
58 | assert_equal "UpcaseMiddleware, DowncaseMiddleware", response['X-Tests']
59 | end
60 |
61 | it "works when app is used as middleware" do
62 | @app.use UpcaseMiddleware
63 | @app = @app.new
64 | get '/Foo'
65 | assert_equal "/FOO", body
66 | assert_equal "UpcaseMiddleware", response['X-Tests']
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/public/_utils/script/test/http.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.http = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 |
17 | // bug COUCHDB-100: DELETE on non-existent DB returns 500 instead of 404
18 | db.deleteDb();
19 |
20 | db.createDb();
21 |
22 | // PUT on existing DB should return 412 instead of 500
23 | if (debug) debugger;
24 |
25 | var xhr = CouchDB.request("PUT", "/test_suite_db/test", {body: "{}"});
26 | var host = CouchDB.host;
27 |
28 | TEquals("http://" + host + "/test_suite_db/test",
29 | xhr.getResponseHeader("Location"),
30 | "should include ip address");
31 |
32 | xhr = CouchDB.request("PUT", "/test_suite_db/test2", {
33 | body: "{}",
34 | headers: {"X-Forwarded-Host": "mysite.com"}
35 | });
36 |
37 | TEquals("http://mysite.com/test_suite_db/test2",
38 | xhr.getResponseHeader("Location"),
39 | "should include X-Forwarded-Host");
40 |
41 | run_on_modified_server([{
42 | section:"httpd",
43 | key:"x_forwarded_host",
44 | value:"X-Host"}],
45 | function() {
46 | xhr = CouchDB.request("PUT", "/test_suite_db/test3", {
47 | body: "{}",
48 | headers: {"X-Host": "mysite2.com"}
49 | });
50 | TEquals("http://mysite2.com/test_suite_db/test3",
51 | xhr.getResponseHeader("Location"),
52 | "should include X-Host");
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/public/_utils/script/test/view_multi_key_all_docs.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.view_multi_key_all_docs = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var docs = makeDocs(0, 100);
20 | db.bulkSave(docs);
21 |
22 | var keys = ["10","15","30","37","50"];
23 | var rows = db.allDocs({},keys).rows;
24 | T(rows.length == keys.length);
25 | for(var i=0; i' }
14 | assert ok?
15 | assert_equal '2', body
16 | end
17 |
18 | it 'renders .erb files in views path' do
19 | erb_app { erb :hello }
20 | assert ok?
21 | assert_equal "Hello World\n", body
22 | end
23 |
24 | it 'takes a :locals option' do
25 | erb_app {
26 | locals = {:foo => 'Bar'}
27 | erb '<%= foo %>', :locals => locals
28 | }
29 | assert ok?
30 | assert_equal 'Bar', body
31 | end
32 |
33 | it "renders with inline layouts" do
34 | mock_app {
35 | layout { 'THIS. IS. <%= yield.upcase %>!' }
36 | get('/') { erb 'Sparta' }
37 | }
38 | get '/'
39 | assert ok?
40 | assert_equal 'THIS. IS. SPARTA!', body
41 | end
42 |
43 | it "renders with file layouts" do
44 | erb_app {
45 | erb 'Hello World', :layout => :layout2
46 | }
47 | assert ok?
48 | assert_equal "ERB Layout!\nHello World\n", body
49 | end
50 |
51 | it "renders erb with blocks" do
52 | mock_app {
53 | def container
54 | @_out_buf << "THIS."
55 | yield
56 | @_out_buf << "SPARTA!"
57 | end
58 | def is; "IS." end
59 | get '/' do
60 | erb '<% container do %> <%= is %> <% end %>'
61 | end
62 | }
63 | get '/'
64 | assert ok?
65 | assert_equal 'THIS. IS. SPARTA!', body
66 | end
67 |
68 | it "can be used in a nested fashion for partials and whatnot" do
69 | mock_app {
70 | template(:inner) { "<%= 'hi' %>" }
71 | template(:outer) { "<%= erb :inner %>" }
72 | get '/' do
73 | erb :outer
74 | end
75 | }
76 |
77 | get '/'
78 | assert ok?
79 | assert_equal 'hi', body
80 | end
81 | end
82 |
--------------------------------------------------------------------------------
/public/_utils/script/test/batch_save.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.batch_save = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // commit should work fine with no batches
20 | T(db.ensureFullCommit().ok);
21 |
22 | // PUT a doc with ?batch=ok
23 | T(db.save({_id:"0",a:1,b:1}, {batch : "ok"}).ok);
24 |
25 | // test that response is 202 Accepted
26 | T(db.last_req.status == 202);
27 |
28 | T(db.allDocs().total_rows == 0);
29 |
30 | restartServer();
31 |
32 | // lost the updates
33 | T(db.allDocs().total_rows == 0);
34 |
35 | T(db.save({_id:"0",a:1,b:1}, {batch : "ok"}).ok);
36 | T(db.save({_id:"1",a:1,b:1}, {batch : "ok"}).ok);
37 | T(db.save({_id:"2",a:1,b:1}, {batch : "ok"}).ok);
38 |
39 | T(db.ensureFullCommit().ok);
40 | T(db.allDocs().total_rows == 3);
41 |
42 | // repeat the tests for POST
43 | var resp = db.request("POST", db.uri + "?batch=ok", {body: JSON.stringify({a:1})});
44 | T(JSON.parse(resp.responseText).ok);
45 |
46 | // test that response is 202 Accepted
47 | T(resp.status == 202);
48 |
49 | T(db.allDocs().total_rows == 3);
50 | // restartServer();
51 | // // lost the POSTed doc
52 | // T(db.allDocs().total_rows == 3);
53 |
54 | var resp = db.request("POST", db.uri + "?batch=ok", {body: JSON.stringify({a:1})});
55 | T(JSON.parse(resp.responseText).ok);
56 |
57 | T(db.ensureFullCommit().ok);
58 | T(db.allDocs().total_rows == 5);
59 |
60 | };
61 |
--------------------------------------------------------------------------------
/spec/document_spec.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.expand_path(File.dirname(__FILE__)),"spec_helper");
2 |
3 | describe "Doc" do
4 | before(:each) do
5 | @d = Document.new({
6 | "_id" => "awesome",
7 | "foo" => "bar"
8 | })
9 | end
10 | it "should have an id" do
11 | @d.id.should == "awesome"
12 | end
13 | it "should have a rev" do
14 | @d.rev.should_not be_nil
15 | end
16 | it "should have body" do
17 | @d.body["foo"].should == "bar"
18 | end
19 | describe "updating it with a matching rev" do
20 | before(:each) do
21 | @r = @d.rev
22 | @d.update({
23 | "_id" => "awesome",
24 | "_rev" => @r,
25 | "foo" => "box"
26 | })
27 | end
28 | it "should get a new rev" do
29 | @d.rev.should_not == @r
30 | end
31 | it "should update fields" do
32 | @d.body["foo"].should == "box"
33 | end
34 | end
35 | describe "deleting a doc" do
36 | before(:each) do
37 | @r = @d.rev
38 | @d.update({
39 | "_id" => "awesome",
40 | "_rev" => @r,
41 | "_deleted" => true
42 | })
43 | end
44 | it "should be deleted" do
45 | @d.deleted.should be_true
46 | end
47 | it "should update without a rev" do
48 | @d.update({
49 | "_id" => "awesome",
50 | "totally_new" => "yeah"
51 | })
52 | @d.jh["totally_new"].should == "yeah"
53 | end
54 | end
55 | describe "updating it with a conflict" do
56 | before(:each) do
57 | @r = @d.rev
58 | @d.update({
59 | "_id" => "awesome",
60 | "_rev" => "@r",
61 | "foo" => "conflict"
62 | },{
63 | :all_or_nothing => "true"
64 | })
65 | @cfts = @d.jh(:conflicts => "true")["_conflicts"]
66 | end
67 | it "should have conflict_revs" do
68 | @cfts.length.should == 1
69 | end
70 | it "should load conflict revs" do
71 | @d.jh({:rev => @cfts[0]})["_rev"].should == @cfts[0]
72 | @d.jh["_rev"].should_not == @cfts[0]
73 | end
74 | end
75 | it "should have no conflicts" do
76 | @d.conflicts.should == []
77 | end
78 | end
79 |
--------------------------------------------------------------------------------
/public/_utils/script/test/lots_of_docs.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | // test saving a semi-large quanitity of documents and do some view queries.
14 | couchTests.lots_of_docs = function(debug) {
15 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
16 | db.deleteDb();
17 | db.createDb();
18 | if (debug) debugger;
19 |
20 | // keep number lowish for now to keep tests fasts. Crank up manually to
21 | // to really test.
22 | var numDocsToCreate = 500;
23 |
24 | for(var i=0; i < numDocsToCreate; i += 100) {
25 | var createNow = Math.min(numDocsToCreate - i, 100);
26 | var docs = makeDocs(i, i + createNow);
27 | db.bulkSave(docs);
28 | }
29 |
30 | // query all documents, and return the doc.integer member as a key.
31 | results = db.query(function(doc){ emit(doc.integer, null) });
32 |
33 | T(results.total_rows == numDocsToCreate);
34 |
35 | // validate the keys are ordered ascending
36 | for(var i=0; i 'foo/bar'}, 'Hello World']
58 | end
59 | }
60 |
61 | get '/'
62 | assert_equal 205, status
63 | assert_equal 'foo/bar', response['Content-Type']
64 | assert_equal 'Hello World', body
65 | end
66 |
67 | it "sets status and body when result is a two-tuple" do
68 | mock_app {
69 | get '/' do
70 | [409, 'formula of']
71 | end
72 | }
73 |
74 | get '/'
75 | assert_equal 409, status
76 | assert_equal 'formula of', body
77 | end
78 |
79 | it "raises a TypeError when result is a non two or three tuple Array" do
80 | mock_app {
81 | get '/' do
82 | [409, 'formula of', 'something else', 'even more']
83 | end
84 | }
85 |
86 | assert_raise(TypeError) { get '/' }
87 | end
88 |
89 | it "sets status when result is a Fixnum status code" do
90 | mock_app {
91 | get('/') { 205 }
92 | }
93 |
94 | get '/'
95 | assert_equal 205, status
96 | assert_equal '', body
97 | end
98 | end
99 |
--------------------------------------------------------------------------------
/public/_utils/script/test/config.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.config = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // test that /_config returns all the settings
20 | var xhr = CouchDB.request("GET", "/_config");
21 | var config = JSON.parse(xhr.responseText);
22 |
23 | /*
24 | if we run on standard ports, we can't extract
25 | the number from the URL. Instead we try to guess
26 | from the protocol what port we are running on.
27 | If we can't guess, we don't test for the port.
28 | Overengineering FTW.
29 | */
30 | var server_port = CouchDB.host.split(':');
31 | if(server_port.length == 1 && CouchDB.inBrowser) {
32 | var proto = window.location.protocol;
33 | if(proto == "http:") {
34 | port = 80;
35 | }
36 | if(proto == "https:") {
37 | port = 443;
38 | }
39 | } else {
40 | port = server_port.pop();
41 | }
42 |
43 | if(port) {
44 | T(config.httpd.port == port);
45 | }
46 |
47 | T(config.couchdb.database_dir);
48 | T(config.daemons.httpd);
49 | T(config.httpd_global_handlers._config);
50 | T(config.log.level);
51 | T(config.query_servers.javascript);
52 |
53 | // test that settings can be altered
54 | xhr = CouchDB.request("PUT", "/_config/test/foo",{
55 | body : JSON.stringify("bar"),
56 | headers: {"X-Couch-Persist": "false"}
57 | });
58 | T(xhr.status == 200);
59 | xhr = CouchDB.request("GET", "/_config/test");
60 | config = JSON.parse(xhr.responseText);
61 | T(config.foo == "bar");
62 |
63 | // you can get a single key
64 | xhr = CouchDB.request("GET", "/_config/test/foo");
65 | config = JSON.parse(xhr.responseText);
66 | T(config == "bar");
67 | };
68 |
--------------------------------------------------------------------------------
/lib/query/query_server.rb:
--------------------------------------------------------------------------------
1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | # use this file except in compliance with the License. You may obtain a copy of
3 | # the License at
4 | #
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | #
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | # License for the specific language governing permissions and limitations under
11 | # the License.
12 |
13 | require 'json'
14 |
15 | class QueryServer
16 | Command = "couchjs #{JS_SERVER_PATH}"
17 | def self.run(trace = false)
18 | puts "launching #{Command}" if trace
19 | if block_given?
20 | IO.popen(Command, "r+") do |io|
21 | qs = QueryServer.new(io, trace)
22 | result = yield qs
23 | qs.close
24 | result
25 | end
26 | else
27 | io = IO.popen(Command, "r+")
28 | QueryServer.new(io, trace)
29 | end
30 | end
31 | def initialize io, trace = false
32 | @qsio = io
33 | @trace = trace
34 | end
35 | def close
36 | @qsio.close
37 | end
38 | def reset!
39 | run(["reset"])
40 | end
41 | def add_fun(fun)
42 | run(["add_fun", fun])
43 | end
44 | def get_chunks
45 | resp = jsgets
46 | raise "not a chunk" unless resp.first == "chunks"
47 | return resp[1]
48 | end
49 | def run json
50 | rrun json
51 | jsgets
52 | end
53 | def rrun json
54 | line = json.to_json
55 | puts "run: #{line}" if @trace
56 | @qsio.puts line
57 | end
58 | def rgets
59 | resp = @qsio.gets
60 | puts "got: #{resp}" if @trace
61 | resp
62 | end
63 | def jsgets
64 | resp = rgets
65 | # err = @qserr.gets
66 | # puts "err: #{err}" if err
67 | if resp
68 | begin
69 | rj = JSON.parse("[#{resp.chomp}]")[0]
70 | rescue JSON::ParserError
71 | puts "JSON ERROR (dump under trace mode)"
72 | # puts resp.chomp
73 | while resp = rgets
74 | # puts resp.chomp
75 | end
76 | end
77 | if rj.respond_to?(:[]) && rj.is_a?(Array)
78 | if rj[0] == "log"
79 | log = rj[1]
80 | puts "log: #{log}" if @trace
81 | rj = jsgets
82 | end
83 | end
84 | rj
85 | else
86 | raise "no response"
87 | end
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/spec/view_spec.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.expand_path(File.dirname(__FILE__)),"spec_helper");
2 |
3 | describe "View" do
4 | before(:each) do
5 | @db = Database.new
6 | @db.put({
7 | "_id" => "zoo",
8 | "foo" => "baz"
9 | })
10 | # make a map-only view based on the db
11 | map = "function(doc) { emit(doc.foo, null); };"
12 | @v = View.new(@db, map)
13 | end
14 | it "should emit the doc" do
15 | result = @v.query
16 | result[:rows].length.should == 1
17 | result[:rows].first[:key].should == "baz"
18 | end
19 | end
20 |
21 | # populate the db with collated docs
22 | describe "View with collated docs" do
23 | before(:each) do
24 | @db = Database.new
25 | @keys = [
26 | nil,
27 | false, true,
28 | 1, 2, 3.4, 5,
29 | "a", "A", "aa", "b", "Ba", "bb",
30 | ["a"], ["b"], ["b","c"], ["b", "c", "a"],
31 | {"a" => 1}, {"a" => 2}, {"b" => 1}, {"b" => 2},
32 | {"b" => 2, "a" => 1}, {"b"=> 2, "c"=> 2}
33 | ]
34 |
35 | @keys.reverse.each_with_index do |key, i|
36 | @db.put({"_id" => i.to_s, "foo" => key})
37 | end
38 |
39 | # make a map-only view based on the db
40 | map = "function(doc) { emit(doc.foo, null); };"
41 | @v = View.new(@db, map)
42 | end
43 | it "should collate properly" do
44 | # puts "view collate"
45 | result = @v.query
46 | result[:rows].each_with_index do |row, i|
47 | # puts "row #{row.inspect}"
48 | row[:key].should == @keys[i]
49 | end
50 | end
51 | it "should support key ranges" do
52 | puts "view key ranges"
53 | rows = []
54 | @v.query("startkey" => "aa", "endkey" => "bb") do |row|
55 | rows << row
56 | end
57 | rows[0][:key].should == "aa"
58 | rows.length.should == 4
59 | rows[3][:key].should == "bb"
60 | end
61 | it "should support short key ranges" do
62 | result = @v.query("startkey" => "aa", "endkey" => "aa", "inclusive_end" => "true")
63 | result[:rows].length.should == 1
64 | result[:rows][0][:key].should == "aa"
65 | end
66 | it "should support key lookups" do
67 | result = @v.query("key" => "aa")
68 | result[:rows].length.should == 1
69 | result[:rows][0][:key].should == "aa"
70 | end
71 | it "should support exclusive end key ranges" do
72 | result = @v.query("startkey" => "aa", "endkey" => "bb", "inclusive_end" => "false")
73 | result[:rows].last[:key].should == "Ba"
74 | result[:rows].length.should == 3
75 | end
76 | end
--------------------------------------------------------------------------------
/vendor/sinatra/AUTHORS:
--------------------------------------------------------------------------------
1 | Sinatra was designed and developed by Blake Mizerany (bmizerany) in
2 | California. Continued development would not be possible without the ongoing
3 | financial support provided by [Heroku](http://heroku.com) and the emotional
4 | support provided by Adam Wiggins (adamwiggins) of Heroku, Chris Wanstrath (defunkt),
5 | PJ Hyett (pjhyett), and the rest of the GitHub crew.
6 |
7 | Special thanks to the following extraordinary individuals, who-out which
8 | Sinatra would not be possible:
9 |
10 | * Ryan Tomayko (rtomayko) for constantly fixing whitespace errors 60d5006
11 | * Ezra Zygmuntowicz (ezmobius) for initial help and letting Blake steal
12 | some of merbs internal code.
13 | * Christopher Schneid (cschneid) for The Book, the blog (gittr.com),
14 | irclogger.com, and a bunch of useful patches.
15 | * Markus Prinz (cypher) for patches over the years, caring about
16 | the README, and hanging in there when times were rough.
17 | * Simon Rozet (sr) for a ton of doc patches, HAML options, and all that
18 | advocacy stuff he's going to do for 1.0.
19 | * Erik Kastner (kastner) for fixing `MIME_TYPES` under Rack 0.5.
20 | * Ben Bleything (bleything) for caring about HTTP status codes and doc fixes.
21 | * Igal Koshevoy (igal) for root path detection under Thin/Passenger.
22 | * Jon Crosby (jcrosby) for coffee breaks, doc fixes, and just because, man.
23 | * Karel Minarik (karmi) for screaming until the website came back up.
24 | * Jeremy Evans (jeremyevans) for unbreaking optional path params (twice!)
25 | * The GitHub guys for stealing Blake's table.
26 | * Nickolas Means (nmeans) for Sass template support.
27 | * Victor Hugo Borja (vic) for splat'n routes specs and doco.
28 | * Avdi Grimm (avdi) for basic RSpec support.
29 | * Jack Danger Canty for a more accurate root directory and for making me
30 | watch [this](http://www.youtube.com/watch?v=ueaHLHgskkw) just now.
31 | * Mathew Walker for making escaped paths work with static files.
32 | * Millions of Us for having the problem that led to Sinatra's conception.
33 | * Songbird for the problems that helped Sinatra's future become realized.
34 | * Rick Olson (technoweenie) for the killer plug at RailsConf '08.
35 | * Steven Garcia for the amazing custom artwork you see on 404's and 500's
36 | * Pat Nakajima (nakajima) for fixing non-nested params in nested params Hash's.
37 |
38 |
39 | and last but not least:
40 |
41 | * Frank Sinatra (chairman of the board) for having so much class he
42 | deserves a web-framework named after him.
43 |
--------------------------------------------------------------------------------
/public/_utils/script/test/design_options.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.design_options = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | //// test the includes_design option
20 | var map = "function (doc) {emit(null, doc._id);}";
21 | var withseq = "function(doc) {emit(doc._local_seq, null)}"
22 |
23 | // we need a design doc even to test temp views with it
24 | var designDoc = {
25 | _id:"_design/fu",
26 | language: "javascript",
27 | options: {
28 | include_design: true,
29 | local_seq: true
30 | },
31 | views: {
32 | data: {"map": map},
33 | with_seq : {"map" : withseq}
34 | }
35 | };
36 | T(db.save(designDoc).ok);
37 |
38 | // should work for temp views
39 | var rows = db.query(map, null, {options:{include_design: true}}).rows;
40 | T(rows.length == 1);
41 | T(rows[0].value == "_design/fu");
42 |
43 | rows = db.query(map).rows;
44 | T(rows.length == 0);
45 |
46 | // when true, should include design docs in views
47 | rows = db.view("fu/data").rows;
48 | T(rows.length == 1);
49 | T(rows[0].value == "_design/fu");
50 |
51 | // when false, should not
52 | designDoc.options.include_design = false;
53 | delete designDoc._rev;
54 | designDoc._id = "_design/bingo";
55 | T(db.save(designDoc).ok);
56 | rows = db.view("bingo/data").rows;
57 | T(rows.length == 0);
58 |
59 | // should default to false
60 | delete designDoc.options;
61 | delete designDoc._rev;
62 | designDoc._id = "_design/bango";
63 | T(db.save(designDoc).ok);
64 | rows = db.view("bango/data").rows;
65 | T(rows.length == 0);
66 |
67 | // should also have local_seq in the view
68 | var resp = db.save({});
69 | rows = db.view("fu/with_seq").rows;
70 | T(rows[0].key == 1)
71 | T(rows[1].key == 2)
72 | var doc = db.open(resp.id);
73 | db.deleteDoc(doc);
74 | };
75 |
--------------------------------------------------------------------------------
/public/_utils/script/test/etags_head.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.etags_head = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var xhr;
20 |
21 | // create a new doc
22 | xhr = CouchDB.request("PUT", "/test_suite_db/1", {
23 | body: "{}"
24 | });
25 | T(xhr.status == 201);
26 |
27 | // extract the ETag header values
28 | var etag = xhr.getResponseHeader("etag");
29 |
30 | // get the doc and verify the headers match
31 | xhr = CouchDB.request("GET", "/test_suite_db/1");
32 | T(etag == xhr.getResponseHeader("etag"));
33 |
34 | // 'head' the doc and verify the headers match
35 | xhr = CouchDB.request("HEAD", "/test_suite_db/1", {
36 | headers: {"if-none-match": "s"}
37 | });
38 | T(etag == xhr.getResponseHeader("etag"));
39 |
40 | // replace a doc
41 | xhr = CouchDB.request("PUT", "/test_suite_db/1", {
42 | body: "{}",
43 | headers: {"if-match": etag}
44 | });
45 | T(xhr.status == 201);
46 |
47 | // extract the new ETag value
48 | var etagOld= etag;
49 | etag = xhr.getResponseHeader("etag");
50 |
51 | // fail to replace a doc
52 | xhr = CouchDB.request("PUT", "/test_suite_db/1", {
53 | body: "{}"
54 | });
55 | T(xhr.status == 409);
56 |
57 | // verify get w/Etag
58 | xhr = CouchDB.request("GET", "/test_suite_db/1", {
59 | headers: {"if-none-match": etagOld}
60 | });
61 | T(xhr.status == 200);
62 | xhr = CouchDB.request("GET", "/test_suite_db/1", {
63 | headers: {"if-none-match": etag}
64 | });
65 | T(xhr.status == 304);
66 |
67 | // fail to delete a doc
68 | xhr = CouchDB.request("DELETE", "/test_suite_db/1", {
69 | headers: {"if-match": etagOld}
70 | });
71 | T(xhr.status == 409);
72 |
73 | //now do it for real
74 | xhr = CouchDB.request("DELETE", "/test_suite_db/1", {
75 | headers: {"if-match": etag}
76 | });
77 | T(xhr.status == 200);
78 | };
79 |
--------------------------------------------------------------------------------
/public/_utils/script/test/design_paths.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.design_paths = function(debug) {
14 | if (debug) debugger;
15 | var dbNames = ["test_suite_db", "test_suite_db/with_slashes"];
16 | for (var i=0; i < dbNames.length; i++) {
17 | var db = new CouchDB(dbNames[i]);
18 | var dbName = encodeURIComponent(dbNames[i]);
19 | db.deleteDb();
20 | db.createDb();
21 |
22 | // create a ddoc w bulk_docs
23 | db.bulkSave([{
24 | _id : "_design/test",
25 | views : {
26 | "testing" : {
27 | "map" : "function(){emit(1,1)}"
28 | }
29 | }
30 | }]);
31 |
32 | // ddoc is getable
33 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test");
34 | var resp = JSON.parse(xhr.responseText);
35 | T(resp._id == "_design/test");
36 |
37 | // it's at 2 urls...
38 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Ftest");
39 | var resp = JSON.parse(xhr.responseText);
40 | T(resp._id == "_design/test");
41 |
42 | // ensure that views are addressable
43 | resp = db.view("test/testing")
44 | T(resp.total_rows == 0)
45 |
46 | // create a ddoc by putting to url with raw slash
47 | var xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test2",{
48 | body : JSON.stringify({
49 | _id : "_design/test2",
50 | views : {
51 | "testing" : {
52 | "map" : "function(){emit(1,1)}"
53 | }
54 | }
55 | })
56 | });
57 |
58 | // ddoc is getable
59 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test2");
60 | var resp = JSON.parse(xhr.responseText);
61 | T(resp._id == "_design/test2");
62 |
63 | // it's at 2 urls...
64 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Ftest2");
65 | var resp = JSON.parse(xhr.responseText);
66 | T(resp._id == "_design/test2");
67 |
68 | // ensure that views are addressable
69 | resp = db.view("test2/testing");
70 | T(resp.total_rows == 0);
71 | };
72 | };
73 |
--------------------------------------------------------------------------------
/spec/database_spec.rb:
--------------------------------------------------------------------------------
1 | require File.join(File.expand_path(File.dirname(__FILE__)),"spec_helper");
2 |
3 | describe "Database" do
4 | before(:each) do
5 | @db = Database.new
6 | @db.put({
7 | "_id" => "foo",
8 | "bam" => "baz"
9 | })
10 | end
11 | it "should count docs" do
12 | @db.doc_count.should == 1
13 | end
14 | it "should accept docs" do
15 | d = @db.get("foo")
16 | d.id.should == "foo"
17 | d.body["bam"].should == "baz"
18 | end
19 | # move rev handling to doc spec
20 | # it "should apply revs" do
21 | # d = @db.get("foo")
22 | # d.rev.should_not be_empty
23 | # end
24 | it "should apply a sequence" do
25 | @db.put({
26 | "_id" => "bar",
27 | "bam" => "dog"
28 | })
29 | d = @db.get("foo")
30 | d.seq.should == 1
31 | d2 = @db.get("bar")
32 | d2.seq.should == 2
33 | @db.seq.should == 2
34 | end
35 | # it "should fail updates with a bad rev" do
36 | # lambda {
37 | # @db.put({
38 | # "_id" => "foo",
39 | # "_rev" => "555",
40 | # "bam" => "duck"
41 | # })
42 | # }.should raise_error
43 | # end
44 | # it "should allow updates with a good rev" do
45 | # d = @db.get("foo")
46 | # d["bam"].should == "baz"
47 | # new_rev = @db.put({
48 | # "_id" => "foo",
49 | # "_rev" => d.rev,
50 | # "bam" => "duck"
51 | # })
52 | # dx = @db.get("foo")
53 | # dx.rev.should == new_rev
54 | # new_rev.should != d.rev
55 | # dx["bam"].should == "duck"
56 | # end
57 | describe "seq" do
58 | before(:each) do
59 | @db.put({
60 | "_id" => "bar",
61 | "bam" => "dog"
62 | })
63 | end
64 | it "should increment on doc" do
65 | d = @db.get("foo")
66 | d.seq.should == 1
67 | @db.put({
68 | "_id" => "foo",
69 | "_rev" => d.rev,
70 | "bam" => "duck"
71 | })
72 | d = @db.get("foo")
73 | d.seq.should == 3
74 | end
75 | it "should be viewable" do
76 | a = []
77 | @db.by_seq({:startkey => 0}) do |k, v|
78 | a << v.id
79 | end
80 | a[0].should == "foo"
81 | a[1].should == "bar"
82 | end
83 | it "should be sparse" do
84 | d = @db.get("foo")
85 | d.seq.should == 1
86 | @db.put({
87 | "_id" => "foo",
88 | "_rev" => d.rev,
89 | "bam" => "duck"
90 | })
91 | a = []
92 | @db.by_seq({:startkey => 0}) do |k, v|
93 | a << v.id
94 | end
95 | a[0].should == "bar"
96 | a[1].should == "foo"
97 | end
98 | end
99 | end
--------------------------------------------------------------------------------
/vendor/sinatra/test/haml_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 | require 'haml'
3 |
4 | class HAMLTest < Test::Unit::TestCase
5 | def haml_app(&block)
6 | mock_app {
7 | set :views, File.dirname(__FILE__) + '/views'
8 | get '/', &block
9 | }
10 | get '/'
11 | end
12 |
13 | it 'renders inline HAML strings' do
14 | haml_app { haml '%h1 Hiya' }
15 | assert ok?
16 | assert_equal "
Hiya
\n", body
17 | end
18 |
19 | it 'renders .haml files in views path' do
20 | haml_app { haml :hello }
21 | assert ok?
22 | assert_equal "
Hello From Haml
\n", body
23 | end
24 |
25 | it "renders with inline layouts" do
26 | mock_app {
27 | layout { %q(%h1= 'THIS. IS. ' + yield.upcase) }
28 | get('/') { haml '%em Sparta' }
29 | }
30 | get '/'
31 | assert ok?
32 | assert_equal "
THIS. IS. SPARTA
\n", body
33 | end
34 |
35 | it "renders with file layouts" do
36 | haml_app {
37 | haml 'Hello World', :layout => :layout2
38 | }
39 | assert ok?
40 | assert_equal "
HAML Layout!
\n
Hello World
\n", body
41 | end
42 |
43 | it "raises error if template not found" do
44 | mock_app {
45 | get('/') { haml :no_such_template }
46 | }
47 | assert_raise(Errno::ENOENT) { get('/') }
48 | end
49 |
50 | it "passes HAML options to the Haml engine" do
51 | mock_app {
52 | get '/' do
53 | haml "!!!\n%h1 Hello World", :format => :html5
54 | end
55 | }
56 | get '/'
57 | assert ok?
58 | assert_equal "\n
Hello World
\n", body
59 | end
60 |
61 | it "passes default HAML options to the Haml engine" do
62 | mock_app {
63 | set :haml, {:format => :html5}
64 | get '/' do
65 | haml "!!!\n%h1 Hello World"
66 | end
67 | }
68 | get '/'
69 | assert ok?
70 | assert_equal "\n
Hello World
\n", body
71 | end
72 |
73 | it "merges the default HAML options with the overrides and passes them to the Haml engine" do
74 | mock_app {
75 | set :haml, {:format => :html5, :attr_wrapper => '"'} # default HAML attr are
76 | get '/' do
77 | haml "!!!\n%h1{:class => :header} Hello World"
78 | end
79 | get '/html4' do
80 | haml "!!!\n%h1{:class => 'header'} Hello World", :format => :html4
81 | end
82 | }
83 | get '/'
84 | assert ok?
85 | assert_equal "\n
Hello World
\n", body
86 | get '/html4'
87 | assert ok?
88 | assert_match(/^ doc.id, :rev => doc.rev}
66 | end
67 | end
68 |
69 | # get a document by id
70 | def get docid, params={}
71 | doc = get_doc(docid, params)
72 | if !doc
73 | raise BoothError.new(404, "not_found", "missing doc '#{docid}'");
74 | elsif doc.deleted
75 | raise BoothError.new(404, "not_found", "deleted doc '#{docid}'");
76 | else
77 | doc
78 | end
79 | end
80 |
81 | # delete a document by id
82 | def delete docid, rev
83 | doc = {
84 | "_id" => docid,
85 | "_rev" => rev,
86 | "_deleted" => true
87 | }
88 | new_rev = put doc
89 | @doc_count -= 1
90 | new_rev
91 | end
92 |
93 | private
94 |
95 | # this used to handle conflicts and stuff
96 | # before I pushed that code into document.rb
97 | def get_doc docid, params={}
98 | @by_docid[docid]
99 | end
100 | end
--------------------------------------------------------------------------------
/vendor/sinatra/sinatra.gemspec:
--------------------------------------------------------------------------------
1 | Gem::Specification.new do |s|
2 | s.specification_version = 2 if s.respond_to? :specification_version=
3 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4 |
5 | s.name = 'sinatra'
6 | s.version = '0.10.1'
7 | s.date = '2009-10-08'
8 |
9 | s.description = "Classy web-development dressed in a DSL"
10 | s.summary = "Classy web-development dressed in a DSL"
11 |
12 | s.authors = ["Blake Mizerany", "Ryan Tomayko", "Simon Rozet"]
13 | s.email = "sinatrarb@googlegroups.com"
14 |
15 | # = MANIFEST =
16 | s.files = %w[
17 | AUTHORS
18 | CHANGES
19 | LICENSE
20 | README.jp.rdoc
21 | README.rdoc
22 | Rakefile
23 | lib/sinatra.rb
24 | lib/sinatra/base.rb
25 | lib/sinatra/images/404.png
26 | lib/sinatra/images/500.png
27 | lib/sinatra/main.rb
28 | lib/sinatra/showexceptions.rb
29 | lib/tilt.rb
30 | sinatra.gemspec
31 | test/base_test.rb
32 | test/builder_test.rb
33 | test/contest.rb
34 | test/data/reload_app_file.rb
35 | test/erb_test.rb
36 | test/extensions_test.rb
37 | test/filter_test.rb
38 | test/haml_test.rb
39 | test/helper.rb
40 | test/helpers_test.rb
41 | test/mapped_error_test.rb
42 | test/middleware_test.rb
43 | test/options_test.rb
44 | test/request_test.rb
45 | test/response_test.rb
46 | test/result_test.rb
47 | test/route_added_hook_test.rb
48 | test/routing_test.rb
49 | test/sass_test.rb
50 | test/server_test.rb
51 | test/sinatra_test.rb
52 | test/static_test.rb
53 | test/templates_test.rb
54 | test/views/error.builder
55 | test/views/error.erb
56 | test/views/error.haml
57 | test/views/error.sass
58 | test/views/foo/hello.test
59 | test/views/hello.builder
60 | test/views/hello.erb
61 | test/views/hello.haml
62 | test/views/hello.sass
63 | test/views/hello.test
64 | test/views/layout2.builder
65 | test/views/layout2.erb
66 | test/views/layout2.haml
67 | test/views/layout2.test
68 | ]
69 | # = MANIFEST =
70 |
71 | s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
72 |
73 | s.extra_rdoc_files = %w[README.rdoc LICENSE]
74 | s.add_dependency 'rack', '>= 1.0'
75 | s.add_development_dependency 'shotgun', '>= 0.3', '< 1.0'
76 | s.add_development_dependency 'rack-test', '>= 0.3.0'
77 |
78 | s.has_rdoc = true
79 | s.homepage = "http://sinatra.rubyforge.org"
80 | s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra", "--main", "README.rdoc"]
81 | s.require_paths = %w[lib]
82 | s.rubyforge_project = 'sinatra'
83 | s.rubygems_version = '1.1.1'
84 | end
85 |
--------------------------------------------------------------------------------
/public/_utils/script/test/invalid_docids.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.invalid_docids = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // Test _local explicitly first.
20 | T(db.save({"_id": "_local/foo"}).ok);
21 | T(db.open("_local/foo")._id == "_local/foo");
22 |
23 | var urls = [
24 | "/test_suite_db/_local",
25 | "/test_suite_db/_local/",
26 | "/test_suite_db/_local%2F",
27 | "/test_suite_db/_local/foo/bar",
28 | ];
29 |
30 | urls.forEach(function(u) {
31 | var res = db.request("PUT", u, {"body": "{}"});
32 | T(res.status == 400);
33 | T(JSON.parse(res.responseText).error == "bad_request");
34 | });
35 |
36 | //Test non-string
37 | try {
38 | db.save({"_id": 1});
39 | T(1 == 0, "doc id must be string");
40 | } catch(e) {
41 | T(db.last_req.status == 400);
42 | T(e.error == "bad_request");
43 | }
44 |
45 | // Via PUT with _id not in body.
46 | var res = res = db.request("PUT", "/test_suite_db/_other", {"body": "{}"});
47 | T(res.status == 400);
48 | T(JSON.parse(res.responseText).error == "bad_request");
49 |
50 | // Accidental POST to form handling code.
51 | res = db.request("POST", "/test_suite_db/_tmp_view", {"body": "{}"});
52 | T(res.status == 400);
53 | T(JSON.parse(res.responseText).error == "bad_request");
54 |
55 | // Test invalid _prefix
56 | try {
57 | db.save({"_id": "_invalid"});
58 | T(1 == 0, "doc id may not start with underscore");
59 | } catch(e) {
60 | T(db.last_req.status == 400);
61 | T(e.error == "bad_request");
62 | }
63 |
64 | // Test _bulk_docs explicitly.
65 | var docs = [{"_id": "_design/foo"}, {"_id": "_local/bar"}];
66 | db.bulkSave(docs);
67 | docs.forEach(function(d) {T(db.open(d._id)._id == d._id);});
68 |
69 | docs = [{"_id": "_invalid"}];
70 | try {
71 | db.bulkSave(docs);
72 | T(1 == 0, "doc id may not start with underscore, even in bulk docs");
73 | } catch(e) {
74 | T(db.last_req.status == 400);
75 | T(e.error == "bad_request");
76 | }
77 | };
78 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/filter_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class FilterTest < Test::Unit::TestCase
4 | it "executes filters in the order defined" do
5 | count = 0
6 | mock_app do
7 | get('/') { 'Hello World' }
8 | before {
9 | assert_equal 0, count
10 | count = 1
11 | }
12 | before {
13 | assert_equal 1, count
14 | count = 2
15 | }
16 | end
17 |
18 | get '/'
19 | assert ok?
20 | assert_equal 2, count
21 | assert_equal 'Hello World', body
22 | end
23 |
24 | it "allows filters to modify the request" do
25 | mock_app {
26 | get('/foo') { 'foo' }
27 | get('/bar') { 'bar' }
28 | before { request.path_info = '/bar' }
29 | }
30 |
31 | get '/foo'
32 | assert ok?
33 | assert_equal 'bar', body
34 | end
35 |
36 | it "can modify instance variables available to routes" do
37 | mock_app {
38 | before { @foo = 'bar' }
39 | get('/foo') { @foo }
40 | }
41 |
42 | get '/foo'
43 | assert ok?
44 | assert_equal 'bar', body
45 | end
46 |
47 | it "allows redirects in filters" do
48 | mock_app {
49 | before { redirect '/bar' }
50 | get('/foo') do
51 | fail 'before block should have halted processing'
52 | 'ORLY?!'
53 | end
54 | }
55 |
56 | get '/foo'
57 | assert redirect?
58 | assert_equal '/bar', response['Location']
59 | assert_equal '', body
60 | end
61 |
62 | it "does not modify the response with its return value" do
63 | mock_app {
64 | before { 'Hello World!' }
65 | get '/foo' do
66 | assert_equal [], response.body
67 | 'cool'
68 | end
69 | }
70 |
71 | get '/foo'
72 | assert ok?
73 | assert_equal 'cool', body
74 | end
75 |
76 | it "does modify the response with halt" do
77 | mock_app {
78 | before { halt 302, 'Hi' }
79 | get '/foo' do
80 | "should not happen"
81 | end
82 | }
83 |
84 | get '/foo'
85 | assert_equal 302, response.status
86 | assert_equal 'Hi', body
87 | end
88 |
89 | it "gives you access to params" do
90 | mock_app {
91 | before { @foo = params['foo'] }
92 | get('/foo') { @foo }
93 | }
94 |
95 | get '/foo?foo=cool'
96 | assert ok?
97 | assert_equal 'cool', body
98 | end
99 |
100 | it "runs filters defined in superclasses" do
101 | base = Class.new(Sinatra::Base)
102 | base.before { @foo = 'hello from superclass' }
103 |
104 | mock_app(base) {
105 | get('/foo') { @foo }
106 | }
107 |
108 | get '/foo'
109 | assert_equal 'hello from superclass', body
110 | end
111 | end
112 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/sass_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 | require 'sass'
3 |
4 | class SassTest < Test::Unit::TestCase
5 | def sass_app(&block)
6 | mock_app {
7 | set :views, File.dirname(__FILE__) + '/views'
8 | get '/', &block
9 | }
10 | get '/'
11 | end
12 |
13 | it 'renders inline Sass strings' do
14 | sass_app { sass "#sass\n :background-color #FFF\n" }
15 | assert ok?
16 | assert_equal "#sass {\n background-color: #FFF; }\n", body
17 | end
18 |
19 | it 'renders .sass files in views path' do
20 | sass_app { sass :hello }
21 | assert ok?
22 | assert_equal "#sass {\n background-color: #FFF; }\n", body
23 | end
24 |
25 | it 'ignores the layout option' do
26 | sass_app { sass :hello, :layout => :layout2 }
27 | assert ok?
28 | assert_equal "#sass {\n background-color: #FFF; }\n", body
29 | end
30 |
31 | it "raises error if template not found" do
32 | mock_app {
33 | get('/') { sass :no_such_template }
34 | }
35 | assert_raise(Errno::ENOENT) { get('/') }
36 | end
37 |
38 | it "passes SASS options to the Sass engine" do
39 | sass_app {
40 | sass "#sass\n :background-color #FFF\n :color #000\n", :style => :compact
41 | }
42 | assert ok?
43 | assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
44 | end
45 |
46 | it "passes default SASS options to the Sass engine" do
47 | mock_app {
48 | set :sass, {:style => :compact} # default Sass style is :nested
49 | get '/' do
50 | sass "#sass\n :background-color #FFF\n :color #000\n"
51 | end
52 | }
53 | get '/'
54 | assert ok?
55 | assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
56 | end
57 |
58 | it "merges the default SASS options with the overrides and passes them to the Sass engine" do
59 | mock_app {
60 | set :sass, {:style => :compact, :attribute_syntax => :alternate } # default Sass attribute_syntax is :normal (with : in front)
61 | get '/' do
62 | sass "#sass\n background-color: #FFF\n color: #000\n"
63 | end
64 | get '/raised' do
65 | sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded # retains global attribute_syntax settings
66 | end
67 | get '/expanded_normal' do
68 | sass "#sass\n :background-color #FFF\n :color #000\n", :style => :expanded, :attribute_syntax => :normal
69 | end
70 | }
71 | get '/'
72 | assert ok?
73 | assert_equal "#sass { background-color: #FFF; color: #000; }\n", body
74 | assert_raise(Sass::SyntaxError) { get('/raised') }
75 | get '/expanded_normal'
76 | assert ok?
77 | assert_equal "#sass {\n background-color: #FFF;\n color: #000;\n}\n", body
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/static_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class StaticTest < Test::Unit::TestCase
4 | setup do
5 | mock_app {
6 | set :static, true
7 | set :public, File.dirname(__FILE__)
8 | }
9 | end
10 |
11 | it 'serves GET requests for files in the public directory' do
12 | get "/#{File.basename(__FILE__)}"
13 | assert ok?
14 | assert_equal File.read(__FILE__), body
15 | assert_equal File.size(__FILE__).to_s, response['Content-Length']
16 | assert response.headers.include?('Last-Modified')
17 | end
18 |
19 | it 'produces a body that can be iterated over multiple times' do
20 | env = Rack::MockRequest.env_for("/#{File.basename(__FILE__)}")
21 | status, headers, body = @app.call(env)
22 | buf1, buf2 = [], []
23 | body.each { |part| buf1 << part }
24 | body.each { |part| buf2 << part }
25 | assert_equal buf1.join, buf2.join
26 | assert_equal File.read(__FILE__), buf1.join
27 | end
28 |
29 | it 'serves HEAD requests for files in the public directory' do
30 | head "/#{File.basename(__FILE__)}"
31 | assert ok?
32 | assert_equal '', body
33 | assert_equal File.size(__FILE__).to_s, response['Content-Length']
34 | assert response.headers.include?('Last-Modified')
35 | end
36 |
37 | %w[POST PUT DELETE].each do |verb|
38 | it "does not serve #{verb} requests" do
39 | send verb.downcase, "/#{File.basename(__FILE__)}"
40 | assert_equal 404, status
41 | end
42 | end
43 |
44 | it 'serves files in preference to custom routes' do
45 | @app.get("/#{File.basename(__FILE__)}") { 'Hello World' }
46 | get "/#{File.basename(__FILE__)}"
47 | assert ok?
48 | assert body != 'Hello World'
49 | end
50 |
51 | it 'does not serve directories' do
52 | get "/"
53 | assert not_found?
54 | end
55 |
56 | it 'passes to the next handler when the static option is disabled' do
57 | @app.set :static, false
58 | get "/#{File.basename(__FILE__)}"
59 | assert not_found?
60 | end
61 |
62 | it 'passes to the next handler when the public option is nil' do
63 | @app.set :public, nil
64 | get "/#{File.basename(__FILE__)}"
65 | assert not_found?
66 | end
67 |
68 | it '404s when a file is not found' do
69 | get "/foobarbaz.txt"
70 | assert not_found?
71 | end
72 |
73 | it 'serves files when .. path traverses within public directory' do
74 | get "/data/../#{File.basename(__FILE__)}"
75 | assert ok?
76 | assert_equal File.read(__FILE__), body
77 | end
78 |
79 | it '404s when .. path traverses outside of public directory' do
80 | mock_app {
81 | set :static, true
82 | set :public, File.dirname(__FILE__) + '/data'
83 | }
84 | get "/../#{File.basename(__FILE__)}"
85 | assert not_found?
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/public/_utils/script/test/attachment_views.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.attachment_views= function(debug) {
14 |
15 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
16 | db.deleteDb();
17 | db.createDb();
18 | if (debug) debugger;
19 |
20 | // count attachments in a view
21 |
22 | db.bulkSave(makeDocs(0, 10));
23 |
24 | db.bulkSave(makeDocs(10, 20, {
25 | _attachments:{
26 | "foo.txt": {
27 | content_type:"text/plain",
28 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
29 | }
30 | }
31 | }));
32 |
33 | db.bulkSave(makeDocs(20, 30, {
34 | _attachments:{
35 | "foo.txt": {
36 | content_type:"text/plain",
37 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
38 | },
39 | "bar.txt": {
40 | content_type:"text/plain",
41 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
42 | }
43 | }
44 | }));
45 |
46 | db.bulkSave(makeDocs(30, 40, {
47 | _attachments:{
48 | "foo.txt": {
49 | content_type:"text/plain",
50 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
51 | },
52 | "bar.txt": {
53 | content_type:"text/plain",
54 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
55 | },
56 | "baz.txt": {
57 | content_type:"text/plain",
58 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
59 | }
60 | }
61 | }));
62 |
63 | var mapFunction = function(doc) {
64 | var count = 0;
65 |
66 | for(var idx in doc._attachments) {
67 | count = count + 1;
68 | }
69 |
70 | emit(parseInt(doc._id), count);
71 | }
72 |
73 | var reduceFunction = function(key, values) {
74 | return sum(values);
75 | }
76 |
77 | var result = db.query(mapFunction, reduceFunction);
78 |
79 | T(result.rows.length == 1);
80 | T(result.rows[0].value == 60);
81 |
82 | var result = db.query(mapFunction, reduceFunction, {
83 | startkey:10,
84 | endkey:19
85 | });
86 |
87 | T(result.rows.length == 1);
88 | T(result.rows[0].value == 10);
89 |
90 | var result = db.query(mapFunction, reduceFunction, {
91 | startkey:20,
92 | endkey:29
93 | });
94 |
95 | T(result.rows.length == 1);
96 | T(result.rows[0].value == 20);
97 |
98 | };
99 |
--------------------------------------------------------------------------------
/public/_utils/script/test/multiple_rows.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.multiple_rows = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | var nc = {_id:"NC", cities:["Charlotte", "Raleigh"]};
20 | var ma = {_id:"MA", cities:["Boston", "Lowell", "Worcester", "Cambridge", "Springfield"]};
21 | var fl = {_id:"FL", cities:["Miami", "Tampa", "Orlando", "Springfield"]};
22 |
23 | T(db.save(nc).ok);
24 | T(db.save(ma).ok);
25 | T(db.save(fl).ok);
26 |
27 | var generateListOfCitiesAndState = "function(doc) {" +
28 | " for (var i = 0; i < doc.cities.length; i++)" +
29 | " emit(doc.cities[i] + \", \" + doc._id, null);" +
30 | "}";
31 |
32 | var results = db.query(generateListOfCitiesAndState);
33 | var rows = results.rows;
34 |
35 | T(rows[0].key == "Boston, MA");
36 | T(rows[1].key == "Cambridge, MA");
37 | T(rows[2].key == "Charlotte, NC");
38 | T(rows[3].key == "Lowell, MA");
39 | T(rows[4].key == "Miami, FL");
40 | T(rows[5].key == "Orlando, FL");
41 | T(rows[6].key == "Raleigh, NC");
42 | T(rows[7].key == "Springfield, FL");
43 | T(rows[8].key == "Springfield, MA");
44 | T(rows[9].key == "Tampa, FL");
45 | T(rows[10].key == "Worcester, MA");
46 |
47 | // add another city to NC
48 | nc.cities.push("Wilmington");
49 | T(db.save(nc).ok);
50 |
51 | var results = db.query(generateListOfCitiesAndState);
52 | var rows = results.rows;
53 |
54 | T(rows[0].key == "Boston, MA");
55 | T(rows[1].key == "Cambridge, MA");
56 | T(rows[2].key == "Charlotte, NC");
57 | T(rows[3].key == "Lowell, MA");
58 | T(rows[4].key == "Miami, FL");
59 | T(rows[5].key == "Orlando, FL");
60 | T(rows[6].key == "Raleigh, NC");
61 | T(rows[7].key == "Springfield, FL");
62 | T(rows[8].key == "Springfield, MA");
63 | T(rows[9].key == "Tampa, FL");
64 | T(rows[10].key == "Wilmington, NC");
65 | T(rows[11].key == "Worcester, MA");
66 |
67 | // now delete MA
68 | T(db.deleteDoc(ma).ok);
69 |
70 | var results = db.query(generateListOfCitiesAndState);
71 | var rows = results.rows;
72 |
73 | T(rows[0].key == "Charlotte, NC");
74 | T(rows[1].key == "Miami, FL");
75 | T(rows[2].key == "Orlando, FL");
76 | T(rows[3].key == "Raleigh, NC");
77 | T(rows[4].key == "Springfield, FL");
78 | T(rows[5].key == "Tampa, FL");
79 | T(rows[6].key == "Wilmington, NC");
80 | };
81 |
--------------------------------------------------------------------------------
/public/_utils/couch_tests.html:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 | Test Suite
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
42 |
43 |
55 | Note: Each of the tests will block the browser. If the
56 | connection to your CouchDB server is slow, running the tests will take
57 | some time, and you'll not be able to do much with your browser while
58 | a test is being executed.
59 |
60 |
61 |
62 |
Tests
63 |
64 |
65 |
Name
66 |
Status
67 |
Elapsed Time
68 |
Details
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/vendor/sinatra/test/extensions_test.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/helper'
2 |
3 | class ExtensionsTest < Test::Unit::TestCase
4 | module FooExtensions
5 | def foo
6 | end
7 |
8 | private
9 | def im_hiding_in_ur_foos
10 | end
11 | end
12 |
13 | module BarExtensions
14 | def bar
15 | end
16 | end
17 |
18 | module BazExtensions
19 | def baz
20 | end
21 | end
22 |
23 | module QuuxExtensions
24 | def quux
25 | end
26 | end
27 |
28 | module PainExtensions
29 | def foo=(name); end
30 | def bar?(name); end
31 | def fizz!(name); end
32 | end
33 |
34 | it 'will add the methods to the DSL for the class in which you register them and its subclasses' do
35 | Sinatra::Base.register FooExtensions
36 | assert Sinatra::Base.respond_to?(:foo)
37 |
38 | Sinatra::Default.register BarExtensions
39 | assert Sinatra::Default.respond_to?(:bar)
40 | assert Sinatra::Default.respond_to?(:foo)
41 | assert !Sinatra::Base.respond_to?(:bar)
42 | end
43 |
44 | it 'allows extending by passing a block' do
45 | Sinatra::Base.register {
46 | def im_in_ur_anonymous_module; end
47 | }
48 | assert Sinatra::Base.respond_to?(:im_in_ur_anonymous_module)
49 | end
50 |
51 | it 'will make sure any public methods added via Default#register are delegated to Sinatra::Delegator' do
52 | Sinatra::Default.register FooExtensions
53 | assert Sinatra::Delegator.private_instance_methods.
54 | map { |m| m.to_sym }.include?(:foo)
55 | assert !Sinatra::Delegator.private_instance_methods.
56 | map { |m| m.to_sym }.include?(:im_hiding_in_ur_foos)
57 | end
58 |
59 | it 'will handle special method names' do
60 | Sinatra::Default.register PainExtensions
61 | assert Sinatra::Delegator.private_instance_methods.
62 | map { |m| m.to_sym }.include?(:foo=)
63 | assert Sinatra::Delegator.private_instance_methods.
64 | map { |m| m.to_sym }.include?(:bar?)
65 | assert Sinatra::Delegator.private_instance_methods.
66 | map { |m| m.to_sym }.include?(:fizz!)
67 | end
68 |
69 | it 'will not delegate methods on Base#register' do
70 | Sinatra::Base.register QuuxExtensions
71 | assert !Sinatra::Delegator.private_instance_methods.include?("quux")
72 | end
73 |
74 | it 'will extend the Sinatra::Default application by default' do
75 | Sinatra.register BazExtensions
76 | assert !Sinatra::Base.respond_to?(:baz)
77 | assert Sinatra::Default.respond_to?(:baz)
78 | end
79 |
80 | module BizzleExtension
81 | def bizzle
82 | bizzle_option
83 | end
84 |
85 | def self.registered(base)
86 | fail "base should be BizzleApp" unless base == BizzleApp
87 | fail "base should have already extended BizzleExtension" unless base.respond_to?(:bizzle)
88 | base.set :bizzle_option, 'bizzle!'
89 | end
90 | end
91 |
92 | class BizzleApp < Sinatra::Base
93 | end
94 |
95 | it 'sends .registered to the extension module after extending the class' do
96 | BizzleApp.register BizzleExtension
97 | assert_equal 'bizzle!', BizzleApp.bizzle_option
98 | assert_equal 'bizzle!', BizzleApp.bizzle
99 | end
100 | end
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Booth. In-Memory Ruby CouchDB
2 |
3 | Booth is version 0.2. Booth is pre-alpha software right now. The latest milestone reached is support for most Futon database and document operations.
4 |
5 | ## The Test Suite
6 |
7 | Booth is an attempt to get the [CouchDB Test Suite](http://127.0.0.1:5984/_utils/couch_tests.html) to pass against an alternate implementation.
8 |
9 | This should hella easy because the CouchDB Test Suite just runs in the browser.
10 |
11 | ## Protocol
12 |
13 | We think the CouchDB runtime can be implemented with varying levels of support.
14 |
15 | Level 1 would be a basic key value REST API. This is shared in common with a set of existing tools.
16 |
17 | Level 2 includes Map Reduce views.
18 |
19 | Level 3 is support for replication with CouchDB instances.
20 |
21 | Level 4 is support for CouchDB's JavaScript server runtime environment and APIs.
22 |
23 | ## Booth
24 |
25 | Booth is an implementation of CouchDB in Ruby. It's meant as an illustration of CouchDB as a protocol.
26 |
27 | Q: CouchDB uses a robust append only B-Tree implementation for storage, what does Booth use for persistence?
28 | A: Nothing. Booth stores data in Ruby hashes and arrays.
29 |
30 | Q: Does it scale?
31 | A: Who the fuck cares?
32 |
33 | Q: How can I help?
34 | A: Start shouting about Booth on Twitter and I'll probably notice.
35 |
36 | Q: Why "Booth"?
37 | A: It's named after [Special Agent Seeley Booth](http://en.wikipedia.org/wiki/Seeley_Booth) from Bones.
38 |
39 | ## Get Started
40 |
41 | Install the following gems, if you haven't:
42 |
43 | gem install json
44 | gem install sinatra
45 | gem install uuid
46 | gem install cgi
47 |
48 | Booth is just a Sinatra server, so to start it, run:
49 |
50 | ruby lib/booth.rb
51 |
52 | Visit your Booth Futon's test suite page: [http://127.0.0.1:4567/_utils/couch_tests.html](http://127.0.0.1:4567/_utils/couch_tests.html)
53 |
54 | Or just play around in [Futon](http://127.0.0.1:4567/_utils/).
55 |
56 | ## Patches Very Welcome
57 |
58 | Fork. Pick a test, get to green. If you know CouchDB a little, you should be able to tell from it which tests will be easy to fix based on the ones that run.
59 |
60 | Some tests require commenting out -- there are certain features (for instance: keeping old revs around) that Booth doesn't bother with, as it is an in-memory store.
61 |
62 | Also -- incremental improvements help a lot. Even getting one more assertion to pass is a patch I'll merge.
63 |
64 | There is a Ruby RSpec suite you can run like this:
65 |
66 | spec spec/
67 |
68 | But I prefer to run it with autospec
69 |
70 | sudo gem install ZenTest
71 | autospec
72 |
73 | ### Which Patches?
74 |
75 | Replication is not implemented yet. It'll be cool when it is b/c the replicator will work with both Booth and CouchDB endpoints. (You can even replicate between 2 real Couches with the Booth replicator.)
76 |
77 | Show and List are almost hooked up. They need the httpd portion - the query server can basically do the work already.
78 |
79 | Temp views work but Design Doc views aren't implemented yet, although the groundwork is laid. This would be an ambitious patch but not too invasive, if you are feeling like a hackathon.
80 |
81 | Also we need a way to echo chunks to the client instead of buffering. Maybe drop to raw Rack.
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/public/_utils/script/test/attachment_names.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.attachment_names = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // punting on unicode name checks for now
20 | // var binAttDoc = {
21 | // _id: "bin_doc",
22 | // _attachments:{
23 | // "foo\x80txt": {
24 | // content_type:"text/plain",
25 | // data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
26 | // }
27 | // }
28 | // }
29 | //
30 | // // inline attachments
31 | // try {
32 | // db.save(binAttDoc);
33 | // TEquals(1, 2, "Attachment name with non UTF-8 encoding saved. Should never show!");
34 | // } catch (e) {
35 | // TEquals("bad_request", e.error, "attachment_name: inline attachments");
36 | // TEquals("Attachment name is not UTF-8 encoded", e.reason, "attachment_name: inline attachments");
37 | // }
38 | //
39 | //
40 | // // standalone docs
41 | // var bin_data = "JHAPDO*AU£PN ){(3u[d 93DQ9¡€])} ææøo'∂ƒæ≤çæππ•¥∫¶®#†π¶®¥π€ª®˙π8np";
42 | //
43 | // var xhr = (CouchDB.request("PUT", "/test_suite_db/bin_doc3/attachment\x80txt", {
44 | // headers:{"Content-Type":"text/plain;charset=utf-8"},
45 | // body:bin_data
46 | // }));
47 | //
48 | // var resp = JSON.parse(xhr.responseText);
49 | // TEquals(400, xhr.status, "attachment_name: standalone API");
50 | // TEquals("bad_request", resp.error, "attachment_name: standalone API");
51 | // TEquals("Attachment name is not UTF-8 encoded", resp.reason, "attachment_name: standalone API");
52 | //
53 | //
54 | // // bulk docs
55 | // var docs = { docs: [binAttDoc] };
56 | //
57 | // var xhr = CouchDB.request("POST", "/test_suite_db/_bulk_docs", {
58 | // body: JSON.stringify(docs)
59 | // });
60 | //
61 | // var resp = JSON.parse(xhr.responseText);
62 | // TEquals(400, xhr.status, "attachment_name: bulk docs");
63 | // TEquals("bad_request", resp.error, "attachment_name: bulk docs");
64 | // TEquals("Attachment name is not UTF-8 encoded", resp.reason, "attachment_name: bulk docs");
65 |
66 |
67 | // leading underscores
68 | var binAttDoc = {
69 | _id: "bin_doc2",
70 | _attachments:{
71 | "_foo.txt": {
72 | content_type:"text/plain",
73 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
74 | }
75 | }
76 | }
77 |
78 | try {
79 | db.save(binAttDoc);
80 | TEquals(1, 2, "Attachment name with leading underscore saved. Should never show!");
81 | } catch (e) {
82 | TEquals("bad_request", e.error, "attachment_name: leading underscore");
83 | TEquals("Attachment name can't start with '_'", e.reason, "attachment_name: leading underscore");
84 | }
85 |
86 | // todo: form uploads, waiting for cmlenz' test case for form uploads
87 |
88 | };
89 |
--------------------------------------------------------------------------------
/public/_utils/script/test/all_docs.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.all_docs = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | // Create some more documents.
20 | // Notice the use of the ok member on the return result.
21 | T(db.save({_id:"0",a:1,b:1}).ok);
22 | T(db.save({_id:"3",a:4,b:16}).ok);
23 | T(db.save({_id:"1",a:2,b:4}).ok);
24 | T(db.save({_id:"2",a:3,b:9}).ok);
25 |
26 | // Check the all docs
27 | var results = db.allDocs();
28 | var rows = results.rows;
29 |
30 | T(results.total_rows == results.rows.length);
31 |
32 | for(var i=0; i < rows.length; i++) {
33 | T(rows[i].id >= "0" && rows[i].id <= "4");
34 | }
35 |
36 | // Check _all_docs with descending=true
37 | var desc = db.allDocs({descending:true});
38 | T(desc.total_rows == desc.rows.length);
39 |
40 | // Check _all_docs offset
41 | // var all = db.allDocs({startkey:"2"});
42 | // T(all.offset == 2);
43 | // Booth doesn't have offset yet.
44 |
45 | // check that the docs show up in the seq view in the order they were created
46 | var changes = db.changes();
47 | var ids = ["0","3","1","2"];
48 | for (var i=0; i < changes.results.length; i++) {
49 | var row = changes.results[i];
50 | T(row.id == ids[i], "seq order");
51 | };
52 |
53 | // it should work in reverse as well
54 | changes = db.changes({descending:true});
55 | ids = ["2","1","3","0"];
56 | for (var i=0; i < changes.results.length; i++) {
57 | var row = changes.results[i];
58 | T(row.id == ids[i], "descending=true");
59 | };
60 |
61 | // check that deletions also show up right
62 | var doc1 = db.open("1");
63 | var deleted = db.deleteDoc(doc1);
64 | T(deleted.ok);
65 | changes = db.changes();
66 | // the deletion should make doc id 1 have the last seq num
67 | T(changes.results.length == 4);
68 | T(changes.results[3].id == "1");
69 | T(changes.results[3].deleted);
70 |
71 | // do an update
72 | var doc2 = db.open("3");
73 | doc2.updated = "totally";
74 | db.save(doc2);
75 | changes = db.changes();
76 |
77 | // the update should make doc id 3 have the last seq num
78 | T(changes.results.length == 4);
79 | T(changes.results[3].id == "3");
80 |
81 | // ok now lets see what happens with include docs
82 | changes = db.changes({include_docs: true});
83 | T(changes.results.length == 4);
84 | T(changes.results[3].id == "3");
85 | T(changes.results[3].doc.updated == "totally");
86 |
87 | T(changes.results[2].doc);
88 | T(changes.results[2].doc._deleted);
89 |
90 | // test the all docs collates sanely
91 | db.save({_id: "Z", foo: "Z"});
92 | db.save({_id: "a", foo: "a"});
93 | // console.log(db.allDocs({startkey: "A"}).rows);
94 | var rows = db.allDocs({startkey: "Z", endkey: "Z "}).rows;
95 | T(rows.length == 1);
96 | };
97 |
--------------------------------------------------------------------------------
/public/_utils/script/test/purge.js:
--------------------------------------------------------------------------------
1 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not
2 | // use this file except in compliance with the License. You may obtain a copy of
3 | // the License at
4 | //
5 | // http://www.apache.org/licenses/LICENSE-2.0
6 | //
7 | // Unless required by applicable law or agreed to in writing, software
8 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 | // License for the specific language governing permissions and limitations under
11 | // the License.
12 |
13 | couchTests.purge = function(debug) {
14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
15 | db.deleteDb();
16 | db.createDb();
17 | if (debug) debugger;
18 |
19 | /*
20 | purge is not to be confused with a document deletion. It removes the
21 | document and all edit history from the local instance of the database.
22 | */
23 |
24 | var numDocs = 10;
25 |
26 | var designDoc = {
27 | _id:"_design/test",
28 | language: "javascript",
29 | views: {
30 | all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"},
31 | single_doc: {map: "function(doc) { if (doc._id == \"1\") { emit(1, null) }}"}
32 | }
33 | }
34 |
35 | T(db.save(designDoc).ok);
36 |
37 | db.bulkSave(makeDocs(1, numDocs + 1));
38 |
39 | // go ahead and validate the views before purging
40 | var rows = db.view("test/all_docs_twice").rows;
41 | for (var i = 0; i < numDocs; i++) {
42 | T(rows[2*i].key == i+1);
43 | T(rows[(2*i)+1].key == i+1);
44 | }
45 | T(db.view("test/single_doc").total_rows == 1);
46 |
47 | var info = db.info();
48 | var doc1 = db.open("1");
49 | var doc2 = db.open("2");
50 |
51 | // purge the documents
52 | var xhr = CouchDB.request("POST", "/test_suite_db/_purge", {
53 | body: JSON.stringify({"1":[doc1._rev], "2":[doc2._rev]}),
54 | });
55 | T(xhr.status == 200);
56 |
57 | var newInfo = db.info();
58 | // purging increments the update sequence
59 | T(info.update_seq+1 == newInfo.update_seq);
60 | // and it increments the purge_seq
61 | T(info.purge_seq+1 == newInfo.purge_seq);
62 |
63 | var result = JSON.parse(xhr.responseText);
64 | T(result.purged["1"][0] == doc1._rev);
65 | T(result.purged["2"][0] == doc2._rev);
66 |
67 | T(db.open("1") == null);
68 | T(db.open("2") == null);
69 |
70 | var rows = db.view("test/all_docs_twice").rows;
71 | for (var i = 2; i < numDocs; i++) {
72 | T(rows[2*(i-2)].key == i+1);
73 | T(rows[(2*(i-2))+1].key == i+1);
74 | }
75 | T(db.view("test/single_doc").total_rows == 0);
76 |
77 | // purge documents twice in a row without loading views
78 | // (causes full view rebuilds)
79 |
80 | var doc3 = db.open("3");
81 | var doc4 = db.open("4");
82 |
83 | xhr = CouchDB.request("POST", "/test_suite_db/_purge", {
84 | body: JSON.stringify({"3":[doc3._rev]}),
85 | });
86 |
87 | T(xhr.status == 200);
88 |
89 | xhr = CouchDB.request("POST", "/test_suite_db/_purge", {
90 | body: JSON.stringify({"4":[doc4._rev]}),
91 | });
92 |
93 | T(xhr.status == 200);
94 |
95 | var rows = db.view("test/all_docs_twice").rows;
96 | for (var i = 4; i < numDocs; i++) {
97 | T(rows[2*(i-4)].key == i+1);
98 | T(rows[(2*(i-4))+1].key == i+1);
99 | }
100 | T(db.view("test/single_doc").total_rows == 0);
101 | };
102 |
--------------------------------------------------------------------------------
/public/_utils/index.html:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 | Overview
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
51 |
52 |
53 |