├── html ├── style │ └── main.css ├── css │ ├── index.css │ ├── tutorial.css │ └── docs.css ├── js │ ├── worker-map-reducer.js │ ├── test │ │ ├── form_submit.js │ │ ├── large_docs.js │ │ ├── reduce_false_temp.js │ │ ├── view_multi_key_temp.js │ │ ├── content_negotiation.js │ │ ├── view_xml.js │ │ ├── utf8.js │ │ ├── batch_save.js │ │ ├── reduce_false.js │ │ ├── view_conflicts.js │ │ ├── copy_doc.js │ │ ├── compact.js │ │ ├── http.js │ │ ├── view_multi_key_all_docs.js │ │ ├── view_sandboxing.js │ │ ├── lots_of_docs.js │ │ ├── conflicts.js │ │ ├── jsonp.js │ │ ├── config.js │ │ ├── design_options.js │ │ ├── etags_head.js │ │ ├── design_paths.js │ │ ├── recreate_doc.js │ │ ├── invalid_docids.js │ │ ├── attachment_views.js │ │ ├── multiple_rows.js │ │ ├── attachment_names.js │ │ ├── all_docs.js │ │ ├── rev_stemming.js │ │ ├── bulk_docs.js │ │ ├── purge.js │ │ ├── users_db.js │ │ ├── view_offsets.js │ │ ├── uuids.js │ │ ├── view_collation.js │ │ ├── delayed_commits.js │ │ ├── view_collation_raw.js │ │ ├── view_pagination.js │ │ ├── etags_views.js │ │ ├── proxyauth.js │ │ ├── view_multi_key_design.js │ │ ├── view_include_docs.js │ │ ├── erlang_views.js │ │ ├── reduce_builtin.js │ │ ├── reader_acl.js │ │ ├── update_documents.js │ │ ├── attachment_paths.js │ │ ├── view_errors.js │ │ ├── design_docs.js │ │ └── reduce.js │ ├── ext │ │ ├── lang-proto.js │ │ ├── lang-lua.js │ │ ├── lang-ml.js │ │ ├── lang-sql.js │ │ ├── lang-lisp.js │ │ ├── jquery.dialog.js │ │ ├── uuid.js │ │ └── futon.format.js │ └── tutorial.js ├── big.html ├── tests.html ├── bookmarks.html ├── serialize.html ├── index.html ├── futon.html └── literate_tests.html ├── app.js ├── .hgtags └── README.markdown /html/style/main.css: -------------------------------------------------------------------------------- 1 | /* add styles here */ -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var couchapp = require('couchapp'); 2 | 3 | ddoc = {'_id':'_design/app'} 4 | 5 | couchapp.loadAttachments(ddoc, __dirname); 6 | 7 | exports.app = ddoc; -------------------------------------------------------------------------------- /html/css/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 20em; 3 | font-family: helvetica; 4 | } 5 | 6 | h1 { 7 | font-weight: normal; 8 | } 9 | 10 | .test { 11 | font-family: monospace; 12 | } 13 | 14 | .in-progress { 15 | background-color: yellow; 16 | } 17 | 18 | .successful { 19 | background-color: lawnGreen; 20 | } 21 | 22 | .failed { 23 | background-color: red; 24 | } 25 | 26 | .pending { 27 | } 28 | 29 | .skipped { 30 | background-color: lightGrey; 31 | } 32 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | c6db5e897d6bdb9f366969acb9c63289d3e7293f blog-post 2 | b89ed0374486e7ca0305601b947bc461eb06e13f blog-post 3 | 4450be5d1b2fa4e0068a79480d58491d353363de blog-post 4 | 9a771b8a1702801bd26df1a920beb8802c573b3b blog-post 5 | 17ce8b6be4529909a83e2c78c048e91b2c6255dd blog-post 6 | dbe68e5af673a226aeeee6a9313f0e1e7af0c5de blog-post 7 | ebf8936fc6966cf849fc7359110b46df117eb468 blog-post 8 | c96ebbbe03d6f4f8239671ac340c7a8802424c98 blog-post 9 | 093e51c6aa3ceeaf1141a09a04191e4f3c41cb98 blog-post 10 | af36b00306d006b754e1e44cf00a9cb6da745e97 blog-post 11 | 86158b61b732707876953a4d816af4e33ecc2948 blog-post 12 | -------------------------------------------------------------------------------- /html/js/worker-map-reducer.js: -------------------------------------------------------------------------------- 1 | function map(func, dict) { 2 | var mapDict = {}; 3 | var currDoc; 4 | 5 | function emit(key, value) { 6 | var item = mapDict[key]; 7 | if (!item) 8 | item = mapDict[key] = {keys: [], values: []}; 9 | item.keys.push(currDoc.id); 10 | item.values.push(value); 11 | } 12 | 13 | for (key in dict) { 14 | currDoc = dict[key]; 15 | func(currDoc, emit); 16 | } 17 | 18 | return mapDict; 19 | } 20 | 21 | function onmessage(event) { 22 | var mapFunc = eval("(" + event.data.map + ")"); 23 | postMessage(map(mapFunc, event.data.dict)); 24 | }; 25 | -------------------------------------------------------------------------------- /html/css/tutorial.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: palatino, georgia, verdana, arial, sans-serif; 3 | font-size: 10pt; 4 | text-align: center; 5 | } 6 | 7 | #content { 8 | text-align: left; 9 | margin: 2em auto; 10 | line-height: 1.4em; 11 | display: none; 12 | } 13 | 14 | h1 { 15 | font-weight: normal; 16 | line-height: 1.4em; 17 | } 18 | 19 | .example-code { 20 | font-family: monaco, andale mono, monospace; 21 | font-size: 9pt; 22 | white-space: pre; 23 | padding-left: 2em; 24 | } 25 | 26 | .example-output { 27 | font-family: monaco, andale mono, monospace; 28 | font-size: 9pt; 29 | white-space: pre-wrap; 30 | padding-left: 2em; 31 | color: gray; 32 | } 33 | 34 | .try-code { 35 | border: 1px dotted black; 36 | } 37 | 38 | .intra-wiki { 39 | color: black; 40 | text-decoration: none; 41 | border-bottom: solid 1px gray; 42 | } 43 | 44 | a { 45 | color: black; 46 | text-decoration: underline; 47 | } 48 | -------------------------------------------------------------------------------- /html/big.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 8 | 10 | Browser Big Couch Test 11 | 12 | 13 |

Browser Big Couch Test

14 |

You can read the source code documentation for this test here.

16 |
17 |
18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/ext/lang-proto.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2006 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | /** 17 | * @fileoverview 18 | * Registers a language handler for Protocol Buffers as described at 19 | * http://code.google.com/p/protobuf/. 20 | * 21 | * Based on the lexical grammar at 22 | * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 23 | * 24 | * @author mikesamuel@gmail.com 25 | */ 26 | 27 | PR.registerLangHandler(PR.sourceDecorator({ 28 | keywords: ( 29 | 'bool bytes default double enum extend extensions false fixed32 ' 30 | + 'fixed64 float group import int32 int64 max message option ' 31 | + 'optional package repeated required returns rpc service ' 32 | + 'sfixed32 sfixed64 sint32 sint64 string syntax to true uint32 ' 33 | + 'uint64'), 34 | cStyleComments: true 35 | }), ['proto']); 36 | -------------------------------------------------------------------------------- /html/js/test/reduce_false_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.reduce_false_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 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 mapFun = "function (doc) { emit(doc.integer, doc.integer); }"; 25 | var reduceFun = "function (keys, values) { return sum(values); }"; 26 | 27 | // Test that the reduce works 28 | var res = db.query(mapFun, reduceFun); 29 | T(res.rows.length == 1 && res.rows[0].value == summate(5)); 30 | 31 | //Test that we get our docs back 32 | res = db.query(mapFun, reduceFun, {reduce: false}); 33 | T(res.rows.length == 5); 34 | for(var i=0; i<5; i++) { 35 | T(res.rows[i].value == i+1); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /html/js/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().toXMLString(), 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.toXMLString(), 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 | -------------------------------------------------------------------------------- /html/js/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 3 | 4 | 5 | 6 | 8 | 10 | Browser Couch Tests 11 | 12 | 13 |

Browser Couch Tests

14 |

You can read the source code documentation for these tests here.

16 | 17 | 18 | 19 | 20 | 21 | 22 | 54 | 55 | -------------------------------------------------------------------------------- /html/css/docs.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: palatino, palatino linotype, georgia, serif; 3 | text-align: center; 4 | } 5 | 6 | .popup-enabled { 7 | cursor: pointer; 8 | border-bottom: dotted 1px black; 9 | } 10 | 11 | .popup { 12 | position: absolute; 13 | z-index: 100; 14 | } 15 | 16 | .popup .item { 17 | cursor: pointer; 18 | font-family: helvetica neue, arial, sans-serif; 19 | background-color: #f0f0f0; 20 | color: black; 21 | padding: 3px; 22 | border: black dotted; 23 | border-width: 1px 1px 0 1px; 24 | } 25 | 26 | .popup .selected { 27 | background-color: black; 28 | color: white; 29 | } 30 | 31 | .popup .bottom { 32 | border-bottom: 1px black dotted; 33 | } 34 | 35 | #content { 36 | text-align: left; 37 | margin: 0 auto; 38 | } 39 | 40 | .documentation { 41 | float: left; 42 | line-height: 1.4em; 43 | } 44 | 45 | .documentation h1, .documentation h2 { 46 | font-weight: normal; 47 | line-height: 1.4em; 48 | } 49 | 50 | .nums{ 51 | font-family: consolas, monaco, andale mono, monospace; 52 | float:left; 53 | white-space: pre; 54 | font-size: 70%; 55 | background-color: #d0d0d0; 56 | margin:0; 57 | color:#999; 58 | } 59 | .code { 60 | font-family: consolas, monaco, andale mono, monospace; 61 | float: left; 62 | white-space: pre; 63 | font-size: 70%; 64 | background-color: #f0f0f0; 65 | } 66 | 67 | .divider { 68 | clear: both; 69 | height: 0; 70 | line-height: 0; 71 | } 72 | 73 | /* Prettify */ 74 | .str { color: #800; } 75 | .kwd { color: #b08; } 76 | .com { color: #080; font-style:italic;} 77 | .typ { color: #000; } 78 | .lit { color: #00f; } 79 | .pun { color: #660; } 80 | .pln { color: #000; } 81 | .tag { color: #008; } 82 | .atn { color: #606; } 83 | .atv { color: #080; } 84 | .dec { color: #606; } 85 | 86 | 87 | .toc li.h1{margin-left:10px;} 88 | .toc li.h2{margin-left:20px;} 89 | .toc li.h3{margin-left:30px;} 90 | .toc li.h4{margin-left:40px;} 91 | .toc li.strong{margin-left:50px;} -------------------------------------------------------------------------------- /html/js/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 3 | 4 | 5 | 6 | 8 | 10 | Bookmarks 11 | 12 | 13 | 59 | 60 | 61 | 62 | 63 | 64 |

Bookmarks

65 |

This is an application to demonstrate/experiment with 66 | uses of browsercouch. Explore the code 67 | here. 68 |

69 |
70 |

Loading... 71 |

72 | 73 | 74 | -------------------------------------------------------------------------------- /html/js/test/view_sandboxing.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_sandboxing = 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 doc = {integer: 1, string: "1", array: [1, 2, 3]}; 20 | T(db.save(doc).ok); 21 | /* 22 | // make sure that attempting to change the document throws an error 23 | var results = db.query(function(doc) { 24 | doc.integer = 2; 25 | emit(null, doc); 26 | }); 27 | T(results.total_rows == 0); 28 | 29 | var results = db.query(function(doc) { 30 | doc.array[0] = 0; 31 | emit(null, doc); 32 | }); 33 | T(results.total_rows == 0); 34 | */ 35 | // make sure that a view cannot invoke interpreter internals such as the 36 | // garbage collector 37 | var results = db.query(function(doc) { 38 | gc(); 39 | emit(null, doc); 40 | }); 41 | T(results.total_rows == 0); 42 | 43 | // make sure that a view cannot access the map_funs array defined used by 44 | // the view server 45 | var results = db.query(function(doc) { map_funs.push(1); emit(null, doc) }); 46 | T(results.total_rows == 0); 47 | 48 | // make sure that a view cannot access the map_results array defined used by 49 | // the view server 50 | var results = db.query(function(doc) { map_results.push(1); emit(null, doc) }); 51 | T(results.total_rows == 0); 52 | }; 53 | -------------------------------------------------------------------------------- /html/js/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 3 | 4 | 5 | 6 | 8 | 12 | Serialization 13 | 14 | 15 | 70 | 71 | 72 |

Serialization

73 |
74 | 75 | Add 76 |
77 | 78 | 79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/ext/lang-lua.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for LUA. 20 | * 21 | * 22 | * To use, include prettify.js and this file in your HTML page. 23 | * Then put your code in an HTML tag like 24 | *
(my LUA code)
25 | * 26 | * 27 | * I used http://www.lua.org/manual/5.1/manual.html#2.1 28 | * Because of the long-bracket concept used in strings and comments, LUA does 29 | * not have a regular lexical grammar, but luckily it fits within the space 30 | * of irregular grammars supported by javascript regular expressions. 31 | * 32 | * @author mikesamuel@gmail.com 33 | */ 34 | 35 | PR.registerLangHandler( 36 | PR.createSimpleLexer( 37 | [ 38 | // Whitespace 39 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 40 | // A double or single quoted, possibly multi-line, string. 41 | [PR.PR_STRING, /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] 42 | ], 43 | [ 44 | // A comment is either a line comment that starts with two dashes, or 45 | // two dashes preceding a long bracketed block. 46 | [PR.PR_COMMENT, /^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/], 47 | // A long bracketed block not preceded by -- is a string. 48 | [PR.PR_STRING, /^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/], 49 | [PR.PR_KEYWORD, /^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/, null], 50 | // A number is a hex integer literal, a decimal real literal, or in 51 | // scientific notation. 52 | [PR.PR_LITERAL, 53 | /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], 54 | // An identifier 55 | [PR.PR_PLAIN, /^[a-z_]\w*/i], 56 | // A run of punctuation 57 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0]+/] 58 | ]), 59 | ['lua']); 60 | -------------------------------------------------------------------------------- /html/js/tutorial.js: -------------------------------------------------------------------------------- 1 | // Helper function that displays a JSON-encodable object in a DOM element. 2 | function displayInElement(obj, id) { 3 | ModuleLoader.require( 4 | 'JSON', 5 | function() { 6 | $('#' + id).text(JSON.stringify(obj, null, 2)); 7 | }); 8 | } 9 | 10 | $(window).ready( 11 | function() { 12 | var CHARS_PER_ROW = 80; 13 | 14 | // Get the width of a single monospaced character of code. 15 | var oneCodeCharacter = $('M'); 16 | $(document.body).append(oneCodeCharacter); 17 | var charWidth = oneCodeCharacter.width(); 18 | var charHeight = oneCodeCharacter.height(); 19 | var columnWidth = charWidth * CHARS_PER_ROW; 20 | $(oneCodeCharacter).remove(); 21 | 22 | // Set the width of the content to be the maximum number of 23 | // characters of code that can fit on a line. 24 | $('#content').width(columnWidth); 25 | 26 | // Set up the code editor. 27 | $('.try-code').width(columnWidth); 28 | var tryCodeLines = $('.try-code').text().split('\n').length + 1; 29 | $('.try-code').height(charHeight * tryCodeLines); 30 | 31 | function executeTryCode() { 32 | $('#try-my-view').text(''); 33 | var code = $('.try-code').val(); 34 | eval(code); 35 | } 36 | 37 | $('.try-code').blur(executeTryCode); 38 | $('#content').fadeIn(); 39 | 40 | // Iterate through all the code snippets, gather them for 41 | // execution, and trim them for display. 42 | var snippets = []; 43 | var DONE_FUNC_NAME = 'DONE'; 44 | var DONE_FUNC_CALL = 'DONE();'; 45 | $('.example-code').each( 46 | function() { 47 | var code = $(this).val() || $(this).text(); 48 | if (code.indexOf(DONE_FUNC_CALL) == -1) 49 | code += DONE_FUNC_CALL; 50 | var snippet = {code: code}; 51 | snippets.push(snippet); 52 | code = code.replace(DONE_FUNC_CALL, ''); 53 | code = jQuery.trim(code); 54 | if ($(this).val()) 55 | $(this).val(code); 56 | else 57 | $(this).text(code); 58 | }); 59 | 60 | snippets.reverse(); 61 | 62 | // Now execute all the code snippets. 63 | function executeNextSnippet() { 64 | if (snippets.length) { 65 | var snippet = snippets.pop(); 66 | var dataUri = 'data:text/javascript,' + encodeURI(snippet.code); 67 | var script = document.createElement('script'); 68 | script.setAttribute('src', dataUri); 69 | document.body.appendChild(script); 70 | } 71 | } 72 | 73 | window[DONE_FUNC_NAME] = executeNextSnippet; 74 | 75 | executeNextSnippet(); 76 | }); 77 | -------------------------------------------------------------------------------- /html/js/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 | var result = db.save(doc); 22 | T(result.ok); 23 | var firstRev = result.rev; 24 | T(db.deleteDoc(doc).ok); 25 | 26 | // Now create a new document with the same ID, save it, and then modify it 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 | try { 37 | // COUCHDB-292 now attempt to save the document with a prev that's since 38 | // been deleted and this should generate a conflict exception 39 | db.save({_id:"foo", _rev:firstRev, bar:1}); 40 | T("no save conflict 1" && false); // we shouldn't hit here 41 | } catch (e) { 42 | T(e.error == "conflict"); 43 | } 44 | 45 | var binAttDoc = { 46 | _id: "foo", 47 | _rev:firstRev, 48 | _attachments:{ 49 | "foo.txt": { 50 | content_type:"text/plain", 51 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" 52 | } 53 | } 54 | } 55 | try { 56 | // same as before, but with binary 57 | db.save(binAttDoc); 58 | T("no save conflict 2" && false); // we shouldn't hit here 59 | } catch (e) { 60 | T(e.error == "conflict"); 61 | } 62 | 63 | 64 | try { 65 | // random non-existant prev rev 66 | db.save({_id:"foo", _rev:"1-asfafasdf", bar:1}); 67 | T("no save conflict 3" && false); // we shouldn't hit here 68 | } catch (e) { 69 | T(e.error == "conflict"); 70 | } 71 | 72 | try { 73 | // random non-existant prev rev with bin 74 | binAttDoc._rev = "1-aasasfasdf"; 75 | db.save(binAttDoc); 76 | T("no save conflict 4" && false); // we shouldn't hit here 77 | } catch (e) { 78 | T(e.error == "conflict"); 79 | } 80 | }; 81 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/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 | -------------------------------------------------------------------------------- /html/js/ext/lang-ml.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for OCaml, SML, F# and similar languages. 20 | * 21 | * Based on the lexical grammar at 22 | * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715 23 | * 24 | * @author mikesamuel@gmail.com 25 | */ 26 | 27 | PR.registerLangHandler( 28 | PR.createSimpleLexer( 29 | [ 30 | // Whitespace is made up of spaces, tabs and newline characters. 31 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 32 | // #if ident/#else/#endif directives delimit conditional compilation 33 | // sections 34 | [PR.PR_COMMENT, 35 | /^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i, 36 | null, '#'], 37 | // A double or single quoted, possibly multi-line, string. 38 | // F# allows escaped newlines in strings. 39 | [PR.PR_STRING, /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\''] 40 | ], 41 | [ 42 | // Block comments are delimited by (* and *) and may be 43 | // nested. Single-line comments begin with // and extend to 44 | // the end of a line. 45 | // TODO: (*...*) comments can be nested. This does not handle that. 46 | [PR.PR_COMMENT, /^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/], 47 | [PR.PR_KEYWORD, /^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], 48 | // A number is a hex integer literal, a decimal real literal, or in 49 | // scientific notation. 50 | [PR.PR_LITERAL, 51 | /^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], 52 | [PR.PR_PLAIN, /^(?:[a-z_]\w*[!?#]?|``[^\r\n\t`]*(?:``|$))/i], 53 | // A printable non-space non-special character 54 | [PR.PR_PUNCTUATION, /^[^\t\n\r \xA0\"\'\w]+/] 55 | ]), 56 | ['fs', 'ml']); 57 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 8 | BrowserCouch Documentation 9 | 10 | 11 |
12 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /html/js/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 | var binAttDoc = { 20 | _id: "bin_doc", 21 | _attachments:{ 22 | "foo\x80txt": { 23 | content_type:"text/plain", 24 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" 25 | } 26 | } 27 | } 28 | 29 | // inline attachments 30 | try { 31 | db.save(binAttDoc); 32 | TEquals(1, 2, "Attachment name with non UTF-8 encoding saved. Should never show!"); 33 | } catch (e) { 34 | TEquals("bad_request", e.error, "attachment_name: inline attachments"); 35 | TEquals("Attachment name is not UTF-8 encoded", e.reason, "attachment_name: inline attachments"); 36 | } 37 | 38 | 39 | // standalone docs 40 | var bin_data = "JHAPDO*AU£PN ){(3u[d 93DQ9¡€])} ææøo'∂ƒæ≤çæππ•¥∫¶®#†π¶®¥π€ª®˙π8np"; 41 | 42 | var xhr = (CouchDB.request("PUT", "/test_suite_db/bin_doc3/attachment\x80txt", { 43 | headers:{"Content-Type":"text/plain;charset=utf-8"}, 44 | body:bin_data 45 | })); 46 | 47 | var resp = JSON.parse(xhr.responseText); 48 | TEquals(400, xhr.status, "attachment_name: standalone API"); 49 | TEquals("bad_request", resp.error, "attachment_name: standalone API"); 50 | TEquals("Attachment name is not UTF-8 encoded", resp.reason, "attachment_name: standalone API"); 51 | 52 | 53 | // bulk docs 54 | var docs = { docs: [binAttDoc] }; 55 | 56 | var xhr = CouchDB.request("POST", "/test_suite_db/_bulk_docs", { 57 | body: JSON.stringify(docs) 58 | }); 59 | 60 | var resp = JSON.parse(xhr.responseText); 61 | TEquals(400, xhr.status, "attachment_name: bulk docs"); 62 | TEquals("bad_request", resp.error, "attachment_name: bulk docs"); 63 | TEquals("Attachment name is not UTF-8 encoded", resp.reason, "attachment_name: bulk docs"); 64 | 65 | 66 | // leading underscores 67 | var binAttDoc = { 68 | _id: "bin_doc2", 69 | _attachments:{ 70 | "_foo.txt": { 71 | content_type:"text/plain", 72 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" 73 | } 74 | } 75 | } 76 | 77 | try { 78 | db.save(binAttDoc); 79 | TEquals(1, 2, "Attachment name with leading underscore saved. Should never show!"); 80 | } catch (e) { 81 | TEquals("bad_request", e.error, "attachment_name: leading underscore"); 82 | TEquals("Attachment name can't start with '_'", e.reason, "attachment_name: leading underscore"); 83 | } 84 | 85 | // todo: form uploads, waiting for cmlenz' test case for form uploads 86 | 87 | }; 88 | -------------------------------------------------------------------------------- /html/js/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 | 44 | // check that the docs show up in the seq view in the order they were created 45 | var changes = db.changes(); 46 | var ids = ["0","3","1","2"]; 47 | for (var i=0; i < changes.results.length; i++) { 48 | var row = changes.results[i]; 49 | T(row.id == ids[i], "seq order"); 50 | }; 51 | 52 | // it should work in reverse as well 53 | changes = db.changes({descending:true}); 54 | ids = ["2","1","3","0"]; 55 | for (var i=0; i < changes.results.length; i++) { 56 | var row = changes.results[i]; 57 | T(row.id == ids[i], "descending=true"); 58 | }; 59 | 60 | // check that deletions also show up right 61 | var doc1 = db.open("1"); 62 | var deleted = db.deleteDoc(doc1); 63 | T(deleted.ok); 64 | changes = db.changes(); 65 | // the deletion should make doc id 1 have the last seq num 66 | T(changes.results.length == 4); 67 | T(changes.results[3].id == "1"); 68 | T(changes.results[3].deleted); 69 | 70 | // do an update 71 | var doc2 = db.open("3"); 72 | doc2.updated = "totally"; 73 | db.save(doc2); 74 | changes = db.changes(); 75 | 76 | // the update should make doc id 3 have the last seq num 77 | T(changes.results.length == 4); 78 | T(changes.results[3].id == "3"); 79 | 80 | // ok now lets see what happens with include docs 81 | changes = db.changes({include_docs: true}); 82 | T(changes.results.length == 4); 83 | T(changes.results[3].id == "3"); 84 | T(changes.results[3].doc.updated == "totally"); 85 | 86 | T(changes.results[2].doc); 87 | T(changes.results[2].doc._deleted); 88 | 89 | // test the all docs collates sanely 90 | db.save({_id: "Z", foo: "Z"}); 91 | db.save({_id: "a", foo: "a"}); 92 | 93 | var rows = db.allDocs({startkey: "Z", endkey: "Z"}).rows; 94 | T(rows.length == 1); 95 | }; 96 | -------------------------------------------------------------------------------- /html/js/ext/lang-sql.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for SQL. 20 | * 21 | * 22 | * To use, include prettify.js and this file in your HTML page. 23 | * Then put your code in an HTML tag like 24 | *
(my SQL code)
25 | * 26 | * 27 | * http://savage.net.au/SQL/sql-99.bnf.html is the basis for the grammar, and 28 | * http://msdn.microsoft.com/en-us/library/aa238507(SQL.80).aspx as the basis 29 | * for the keyword list. 30 | * 31 | * @author mikesamuel@gmail.com 32 | */ 33 | 34 | PR.registerLangHandler( 35 | PR.createSimpleLexer( 36 | [ 37 | // Whitespace 38 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 39 | // A double or single quoted, possibly multi-line, string. 40 | [PR.PR_STRING, /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null, 41 | '"\''] 42 | ], 43 | [ 44 | // A comment is either a line comment that starts with two dashes, or 45 | // two dashes preceding a long bracketed block. 46 | [PR.PR_COMMENT, /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/], 47 | [PR.PR_KEYWORD, /^(?:ADD|ALL|ALTER|AND|ANY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|NATIONAL|NOCHECK|NONCLUSTERED|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PERCENT|PLAN|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNION|UNIQUE|UPDATE|UPDATETEXT|USE|USER|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WRITETEXT)(?=[^\w-]|$)/i, null], 48 | // A number is a hex integer literal, a decimal real literal, or in 49 | // scientific notation. 50 | [PR.PR_LITERAL, 51 | /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i], 52 | // An identifier 53 | [PR.PR_PLAIN, /^[a-z_][\w-]*/i], 54 | // A run of punctuation 55 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0]+/] 56 | ]), 57 | ['sql']); 58 | -------------------------------------------------------------------------------- /html/js/test/rev_stemming.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.rev_stemming = function(debug) { 14 | var db = new CouchDB("test_suite_db_a", {"X-Couch-Full-Commit":"false"}); 15 | db.deleteDb(); 16 | db.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 newLimit = 5; 23 | 24 | T(db.getDbProperty("_revs_limit") == 1000); 25 | 26 | var doc = {_id:"foo",foo:0} 27 | for( var i=0; i < newLimit + 1; i++) { 28 | doc.foo++; 29 | T(db.save(doc).ok); 30 | } 31 | var doc0 = db.open("foo", {revs:true}); 32 | T(doc0._revisions.ids.length == newLimit + 1); 33 | 34 | var docBar = {_id:"bar",foo:0} 35 | for( var i=0; i < newLimit + 1; i++) { 36 | docBar.foo++; 37 | T(db.save(docBar).ok); 38 | } 39 | T(db.open("bar", {revs:true})._revisions.ids.length == newLimit + 1); 40 | 41 | T(db.setDbProperty("_revs_limit", newLimit).ok); 42 | 43 | for( var i=0; i < newLimit + 1; i++) { 44 | doc.foo++; 45 | T(db.save(doc).ok); 46 | } 47 | doc0 = db.open("foo", {revs:true}); 48 | T(doc0._revisions.ids.length == newLimit); 49 | 50 | 51 | // If you replicate after you make more edits than the limit, you'll 52 | // cause a spurious edit conflict. 53 | CouchDB.replicate("test_suite_db_a", "test_suite_db_b"); 54 | var docB1 = dbB.open("foo",{conflicts:true}) 55 | T(docB1._conflicts == null); 56 | 57 | for( var i=0; i < newLimit - 1; i++) { 58 | doc.foo++; 59 | T(db.save(doc).ok); 60 | } 61 | 62 | // one less edit than limit, no conflict 63 | CouchDB.replicate("test_suite_db_a", "test_suite_db_b"); 64 | var docB1 = dbB.open("foo",{conflicts:true}) 65 | T(docB1._conflicts == null); 66 | 67 | //now we hit the limit 68 | for( var i=0; i < newLimit; i++) { 69 | doc.foo++; 70 | T(db.save(doc).ok); 71 | } 72 | 73 | CouchDB.replicate("test_suite_db_a", "test_suite_db_b"); 74 | 75 | var docB2 = dbB.open("foo",{conflicts:true}); 76 | 77 | // we have a conflict, but the previous replicated rev is always the losing 78 | // conflict 79 | T(docB2._conflicts[0] == docB1._rev) 80 | 81 | // We having already updated bar before setting the limit, so it's still got 82 | // a long rev history. compact to stem the revs. 83 | 84 | T(db.open("bar", {revs:true})._revisions.ids.length == newLimit + 1); 85 | 86 | T(db.compact().ok); 87 | 88 | // compaction isn't instantaneous, loop until done 89 | while (db.info().compact_running) {}; 90 | 91 | // force reload because ETags don't honour compaction 92 | var req = db.request("GET", "/test_suite_db_a/bar?revs=true", { 93 | headers:{"if-none-match":"pommes"} 94 | }); 95 | 96 | var finalDoc = JSON.parse(req.responseText); 97 | TEquals(newLimit, finalDoc._revisions.ids.length, 98 | "should return a truncated revision list"); 99 | }; 100 | -------------------------------------------------------------------------------- /html/js/test/bulk_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.bulk_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(5); 20 | 21 | // Create the docs 22 | var results = db.bulkSave(docs); 23 | 24 | T(results.length == 5); 25 | for (var i = 0; i < 5; i++) { 26 | T(results[i].id == docs[i]._id); 27 | T(results[i].rev); 28 | // Update the doc 29 | docs[i].string = docs[i].string + ".00"; 30 | } 31 | 32 | // Save the docs 33 | results = db.bulkSave(docs); 34 | T(results.length == 5); 35 | for (i = 0; i < 5; i++) { 36 | T(results[i].id == i.toString()); 37 | 38 | // set the delete flag to delete the docs in the next step 39 | docs[i]._deleted = true; 40 | } 41 | 42 | // now test a bulk update with a conflict 43 | // open and save 44 | var doc = db.open("0"); 45 | db.save(doc); 46 | 47 | // Now bulk delete the docs 48 | results = db.bulkSave(docs); 49 | 50 | // doc "0" should be a conflict 51 | T(results.length == 5); 52 | T(results[0].id == "0"); 53 | T(results[0].error == "conflict"); 54 | T(results[0].rev === undefined); // no rev member when a conflict 55 | 56 | // but the rest are not 57 | for (i = 1; i < 5; i++) { 58 | T(results[i].id == i.toString()); 59 | T(results[i].rev) 60 | T(db.open(docs[i]._id) == null); 61 | } 62 | 63 | // now force a conflict to to save 64 | 65 | // save doc 0, this will cause a conflict when we save docs[0] 66 | var doc = db.open("0"); 67 | docs[0] = db.open("0") 68 | db.save(doc); 69 | 70 | docs[0].shooby = "dooby"; 71 | 72 | // Now save the bulk docs, When we use all_or_nothing, we don't get conflict 73 | // checking, all docs are saved regardless of conflict status, or none are 74 | // saved. 75 | results = db.bulkSave(docs,{all_or_nothing:true}); 76 | T(results.error === undefined); 77 | 78 | var doc = db.open("0", {conflicts:true}); 79 | var docConflict = db.open("0", {rev:doc._conflicts[0]}); 80 | 81 | T(doc.shooby == "dooby" || docConflict.shooby == "dooby"); 82 | 83 | // verify creating a document with no id returns a new id 84 | var req = CouchDB.request("POST", "/test_suite_db/_bulk_docs", { 85 | body: JSON.stringify({"docs": [{"foo":"bar"}]}) 86 | }); 87 | results = JSON.parse(req.responseText); 88 | 89 | T(results[0].id != ""); 90 | T(results[0].rev != ""); 91 | 92 | 93 | // Regression test for failure on update/delete 94 | var newdoc = {"_id": "foobar", "body": "baz"}; 95 | T(db.save(newdoc).ok); 96 | update = {"_id": newdoc._id, "_rev": newdoc._rev, "body": "blam"}; 97 | torem = {"_id": newdoc._id, "_rev": newdoc._rev, "_deleted": true}; 98 | results = db.bulkSave([update, torem]); 99 | T(results[0].error == "conflict" || results[1].error == "conflict"); 100 | }; 101 | -------------------------------------------------------------------------------- /html/futon.html: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | Overview 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 52 | 53 | 54 |
55 |

Overview

56 |
57 |
    58 |
  • 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 88 | 89 | 90 |
Databases
NameSizeNumber of DocumentsUpdate Seq
76 |
77 | | 78 | | 84 | 85 |
86 | 87 |
91 |
92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /html/js/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 result = JSON.parse(xhr.responseText); 58 | var newInfo = db.info(); 59 | 60 | // purging increments the update sequence 61 | T(info.update_seq+1 == newInfo.update_seq); 62 | // and it increments the purge_seq 63 | T(info.purge_seq+1 == newInfo.purge_seq); 64 | T(result.purge_seq == newInfo.purge_seq); 65 | 66 | T(result.purged["1"][0] == doc1._rev); 67 | T(result.purged["2"][0] == doc2._rev); 68 | 69 | T(db.open("1") == null); 70 | T(db.open("2") == null); 71 | 72 | var rows = db.view("test/all_docs_twice").rows; 73 | for (var i = 2; i < numDocs; i++) { 74 | T(rows[2*(i-2)].key == i+1); 75 | T(rows[(2*(i-2))+1].key == i+1); 76 | } 77 | T(db.view("test/single_doc").total_rows == 0); 78 | 79 | // purge documents twice in a row without loading views 80 | // (causes full view rebuilds) 81 | 82 | var doc3 = db.open("3"); 83 | var doc4 = db.open("4"); 84 | 85 | xhr = CouchDB.request("POST", "/test_suite_db/_purge", { 86 | body: JSON.stringify({"3":[doc3._rev]}), 87 | }); 88 | 89 | T(xhr.status == 200); 90 | 91 | xhr = CouchDB.request("POST", "/test_suite_db/_purge", { 92 | body: JSON.stringify({"4":[doc4._rev]}), 93 | }); 94 | 95 | T(xhr.status == 200); 96 | result = JSON.parse(xhr.responseText); 97 | T(result.purge_seq == db.info().purge_seq); 98 | 99 | var rows = db.view("test/all_docs_twice").rows; 100 | for (var i = 4; i < numDocs; i++) { 101 | T(rows[2*(i-4)].key == i+1); 102 | T(rows[(2*(i-4))+1].key == i+1); 103 | } 104 | T(db.view("test/single_doc").total_rows == 0); 105 | }; 106 | -------------------------------------------------------------------------------- /html/js/test/users_db.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 3 | // of 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.users_db = function(debug) { 14 | // This tests the users db, especially validations 15 | // this should also test that you can log into the couch 16 | 17 | var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"}); 18 | 19 | // test that you can treat "_user" as a db-name 20 | // this can complicate people who try to secure the users db with 21 | // an http proxy and fail to get both the actual db and the _user path 22 | // maybe it's not the right approach... 23 | // hard to know what else to do, as we don't let non-admins inspect the config 24 | // to determine the actual users db name. 25 | 26 | function testFun() { 27 | usersDb.deleteDb(); 28 | 29 | // test that the validation function is installed 30 | var ddoc = usersDb.open("_design/_auth"); 31 | T(ddoc.validate_doc_update); 32 | 33 | // test that you can login as a user using basic auth 34 | var jchrisUserDoc = CouchDB.prepareUserDoc({ 35 | name: "jchris@apache.org" 36 | }, "funnybone"); 37 | T(usersDb.save(jchrisUserDoc).ok); 38 | 39 | T(CouchDB.session().userCtx.name == null); 40 | 41 | // test that you can use basic auth aginst the users db 42 | var s = CouchDB.session({ 43 | headers : { 44 | "Authorization" : "Basic amNocmlzQGFwYWNoZS5vcmc6ZnVubnlib25l" 45 | } 46 | }); 47 | T(s.userCtx.name == "jchris@apache.org"); 48 | T(s.info.authenticated == "default"); 49 | T(s.info.authentication_db == "test_suite_users"); 50 | TEquals(["oauth", "cookie", "default"], s.info.authentication_handlers); 51 | var s = CouchDB.session({ 52 | headers : { 53 | "Authorization" : "Basic Xzpf" // name and pass of _:_ 54 | } 55 | }); 56 | T(s.name == null); 57 | T(s.info.authenticated == "default"); 58 | 59 | 60 | // ok, now create a conflicting edit on the jchris doc, and make sure there's no login. 61 | var jchrisUser2 = JSON.parse(JSON.stringify(jchrisUserDoc)); 62 | jchrisUser2.foo = "bar"; 63 | T(usersDb.save(jchrisUser2).ok); 64 | try { 65 | usersDb.save(jchrisUserDoc); 66 | T(false && "should be an update conflict") 67 | } catch(e) { 68 | T(true); 69 | } 70 | // save as bulk with new_edits=false to force conflict save 71 | var resp = usersDb.bulkSave([jchrisUserDoc],{all_or_nothing : true}); 72 | 73 | var jchrisWithConflict = usersDb.open(jchrisUserDoc._id, {conflicts : true}); 74 | T(jchrisWithConflict._conflicts.length == 1) 75 | 76 | // no login with conflicted user doc 77 | try { 78 | var s = CouchDB.session({ 79 | headers : { 80 | "Authorization" : "Basic amNocmlzQGFwYWNoZS5vcmc6ZnVubnlib25l" 81 | } 82 | }); 83 | T(false && "this will throw") 84 | } catch(e) { 85 | T(e.error == "unauthorized") 86 | T(/conflict/.test(e.reason)) 87 | } 88 | 89 | }; 90 | 91 | run_on_modified_server( 92 | [{section: "couch_httpd_auth", 93 | key: "authentication_db", value: "test_suite_users"}], 94 | testFun 95 | ); 96 | 97 | } -------------------------------------------------------------------------------- /html/js/ext/lang-lisp.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2008 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | /** 18 | * @fileoverview 19 | * Registers a language handler for Common Lisp and related languages. 20 | * 21 | * 22 | * To use, include prettify.js and this file in your HTML page. 23 | * Then put your code in an HTML tag like 24 | *
(my lisp code)
25 | * The lang-cl class identifies the language as common lisp. 26 | * This file supports the following language extensions: 27 | * lang-cl - Common Lisp 28 | * lang-el - Emacs Lisp 29 | * lang-lisp - Lisp 30 | * lang-scm - Scheme 31 | * 32 | * 33 | * I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm 34 | * as the basis, but added line comments that start with ; and changed the atom 35 | * production to disallow unquoted semicolons. 36 | * 37 | * "Name" = 'LISP' 38 | * "Author" = 'John McCarthy' 39 | * "Version" = 'Minimal' 40 | * "About" = 'LISP is an abstract language that organizes ALL' 41 | * | 'data around "lists".' 42 | * 43 | * "Start Symbol" = [s-Expression] 44 | * 45 | * {Atom Char} = {Printable} - {Whitespace} - [()"\''] 46 | * 47 | * Atom = ( {Atom Char} | '\'{Printable} )+ 48 | * 49 | * [s-Expression] ::= [Quote] Atom 50 | * | [Quote] '(' [Series] ')' 51 | * | [Quote] '(' [s-Expression] '.' [s-Expression] ')' 52 | * 53 | * [Series] ::= [s-Expression] [Series] 54 | * | 55 | * 56 | * [Quote] ::= '' !Quote = do not evaluate 57 | * | 58 | * 59 | * 60 | * I used Practical Common Lisp as 61 | * the basis for the reserved word list. 62 | * 63 | * 64 | * @author mikesamuel@gmail.com 65 | */ 66 | 67 | PR.registerLangHandler( 68 | PR.createSimpleLexer( 69 | [ 70 | ['opn', /^\(/, null, '('], 71 | ['clo', /^\)/, null, ')'], 72 | // A line comment that starts with ; 73 | [PR.PR_COMMENT, /^;[^\r\n]*/, null, ';'], 74 | // Whitespace 75 | [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], 76 | // A double quoted, possibly multi-line, string. 77 | [PR.PR_STRING, /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'] 78 | ], 79 | [ 80 | [PR.PR_KEYWORD, /^(?:block|c[ad]+r|catch|cons|defun|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null], 81 | [PR.PR_LITERAL, 82 | /^[+\-]?(?:\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[eEdD][+\-]?\d+)?)/], 83 | // A single quote possibly followed by a word that optionally ends with 84 | // = ! or ?. 85 | [PR.PR_LITERAL, 86 | /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/], 87 | // A word that optionally ends with = ! or ?. 88 | [PR.PR_PLAIN, 89 | /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i], 90 | // A printable non-space non-special character 91 | [PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0()\"\\\';]+/] 92 | ]), 93 | ['cl', 'el', 'lisp', 'scm']); 94 | -------------------------------------------------------------------------------- /html/js/test/view_offsets.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_offsets = function(debug) { 14 | if (debug) debugger; 15 | 16 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); 17 | db.deleteDb(); 18 | db.createDb(); 19 | 20 | var designDoc = { 21 | _id : "_design/test", 22 | views : { 23 | offset : { 24 | map : "function(doc) { emit([doc.letter, doc.number], doc); }", 25 | } 26 | } 27 | }; 28 | T(db.save(designDoc).ok); 29 | 30 | var docs = [ 31 | {_id : "a1", letter : "a", number : 1, foo: "bar"}, 32 | {_id : "a2", letter : "a", number : 2, foo: "bar"}, 33 | {_id : "a3", letter : "a", number : 3, foo: "bar"}, 34 | {_id : "b1", letter : "b", number : 1, foo: "bar"}, 35 | {_id : "b2", letter : "b", number : 2, foo: "bar"}, 36 | {_id : "b3", letter : "b", number : 3, foo: "bar"}, 37 | {_id : "b4", letter : "b", number : 4, foo: "bar"}, 38 | {_id : "b5", letter : "b", number : 5, foo: "bar"}, 39 | {_id : "c1", letter : "c", number : 1, foo: "bar"}, 40 | {_id : "c2", letter : "c", number : 2, foo: "bar"}, 41 | ]; 42 | db.bulkSave(docs); 43 | 44 | var check = function(startkey, offset) { 45 | var opts = {startkey: startkey, descending: true}; 46 | T(db.view("test/offset", opts).offset == offset); 47 | }; 48 | 49 | [ 50 | [["c", 2], 0], 51 | [["c", 1], 1], 52 | [["b", 5], 2], 53 | [["b", 4], 3], 54 | [["b", 3], 4], 55 | [["b", 2], 5], 56 | [["b", 1], 6], 57 | [["a", 3], 7], 58 | [["a", 2], 8], 59 | [["a", 1], 9] 60 | ].forEach(function(row){ check(row[0], row[1]);}); 61 | 62 | var runTest = function () { 63 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); 64 | db.deleteDb(); 65 | db.createDb(); 66 | 67 | var designDoc = { 68 | _id : "_design/test", 69 | views : { 70 | offset : { 71 | map : "function(doc) { emit([doc.letter, doc.number], doc);}", 72 | } 73 | } 74 | }; 75 | T(db.save(designDoc).ok); 76 | 77 | var docs = [ 78 | {_id : "a1", letter : "a", number : 1, foo : "bar"}, 79 | {_id : "a2", letter : "a", number : 2, foo : "bar"}, 80 | {_id : "a3", letter : "a", number : 3, foo : "bar"}, 81 | {_id : "b1", letter : "b", number : 1, foo : "bar"}, 82 | {_id : "b2", letter : "b", number : 2, foo : "bar"}, 83 | {_id : "b3", letter : "b", number : 3, foo : "bar"}, 84 | {_id : "b4", letter : "b", number : 4, foo : "bar"}, 85 | {_id : "b5", letter : "b", number : 5, foo : "bar"}, 86 | {_id : "c1", letter : "c", number : 1, foo : "bar"}, 87 | {_id : "c2", letter : "c", number : 2, foo : "bar"} 88 | ]; 89 | db.bulkSave(docs); 90 | 91 | var res1 = db.view("test/offset", { 92 | startkey: ["b",4], startkey_docid: "b4", endkey: ["b"], 93 | limit: 2, descending: true, skip: 1 94 | }) 95 | 96 | var res2 = db.view("test/offset", {startkey: ["c", 3]}); 97 | var res3 = db.view("test/offset", { 98 | startkey: ["b", 6], 99 | endkey: ["b", 7] 100 | }); 101 | 102 | return res1.offset == 4 && res2.offset == docs.length && res3.offset == 8; 103 | 104 | }; 105 | 106 | for(var i = 0; i < 15; i++) T(runTest()); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /html/js/test/uuids.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.uuids = function(debug) { 14 | var etags = []; 15 | var testHashBustingHeaders = function(xhr) { 16 | T(xhr.getResponseHeader("Cache-Control").match(/no-cache/)); 17 | T(xhr.getResponseHeader("Pragma") == "no-cache"); 18 | 19 | var newetag = xhr.getResponseHeader("ETag"); 20 | T(etags.indexOf(newetag) < 0); 21 | etags[etags.length] = newetag; 22 | 23 | // Removing the time based tests as they break easily when 24 | // running CouchDB on a remote server in regards to the browser 25 | // running the Futon test suite. 26 | // 27 | //var currentTime = new Date(); 28 | //var expiresHeader = Date.parse(xhr.getResponseHeader("Expires")); 29 | //var dateHeader = Date.parse(xhr.getResponseHeader("Date")); 30 | 31 | //T(expiresHeader < currentTime); 32 | //T(currentTime - dateHeader < 3000); 33 | }; 34 | 35 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); 36 | db.deleteDb(); 37 | db.createDb(); 38 | if (debug) debugger; 39 | 40 | // a single UUID without an explicit count 41 | var xhr = CouchDB.request("GET", "/_uuids"); 42 | T(xhr.status == 200); 43 | var result = JSON.parse(xhr.responseText); 44 | T(result.uuids.length == 1); 45 | var first = result.uuids[0]; 46 | testHashBustingHeaders(xhr); 47 | 48 | // a single UUID with an explicit count 49 | xhr = CouchDB.request("GET", "/_uuids?count=1"); 50 | T(xhr.status == 200); 51 | result = JSON.parse(xhr.responseText); 52 | T(result.uuids.length == 1); 53 | var second = result.uuids[0]; 54 | T(first != second); 55 | 56 | // no collisions with 1,000 UUIDs 57 | xhr = CouchDB.request("GET", "/_uuids?count=1000"); 58 | T(xhr.status == 200); 59 | result = JSON.parse(xhr.responseText); 60 | T( result.uuids.length == 1000 ); 61 | var seen = {}; 62 | for(var i in result.uuids) { 63 | var id = result.uuids[i]; 64 | T(seen[id] === undefined); 65 | seen[id] = 1; 66 | } 67 | 68 | // ensure we return a 405 on POST 69 | xhr = CouchDB.request("POST", "/_uuids?count=1000"); 70 | T(xhr.status == 405); 71 | 72 | // Test sequential uuids 73 | var seq_testfun = function() { 74 | xhr = CouchDB.request("GET", "/_uuids?count=1000"); 75 | T(xhr.status == 200); 76 | result = JSON.parse(xhr.responseText); 77 | for(var i = 1; i < result.uuids.length; i++) { 78 | T(result.uuids[i].length == 32); 79 | T(result.uuids[i-1] < result.uuids[i], "Sequential uuids are ordered."); 80 | } 81 | }; 82 | 83 | run_on_modified_server([{ 84 | "section": "uuids", 85 | "key": "algorithm", 86 | "value": "sequential", 87 | }], 88 | seq_testfun 89 | ); 90 | 91 | // Test utc_random uuids 92 | var utc_testfun = function() { 93 | xhr = CouchDB.request("GET", "/_uuids?count=1000"); 94 | T(xhr.status == 200); 95 | result = JSON.parse(xhr.responseText); 96 | for(var i = 1; i < result.uuids.length; i++) { 97 | T(result.uuids[i].length == 32); 98 | var u1 = result.uuids[i-1].substr(0, 13); 99 | var u2 = result.uuids[i].substr(0, 13); 100 | T(u1 < u2, "UTC uuids are roughly ordered."); 101 | } 102 | }; 103 | 104 | run_on_modified_server([{ 105 | "section": "uuids", 106 | "key": "algorithm", 107 | "value": "utc_random" 108 | }], 109 | utc_testfun 110 | ); 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /html/js/ext/jquery.dialog.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 | 15 | $.fn.centerBox = function() { 16 | return this.each(function() { 17 | var s = this.style; 18 | s.left = (($(window).width() - $(this).width()) / 2) + "px"; 19 | s.top = (($(window).height() - $(this).height()) / 2) + "px"; 20 | }); 21 | } 22 | 23 | $.showDialog = function(url, options) { 24 | options = options || {}; 25 | options.load = options.load || function() {}; 26 | options.cancel = options.cancel || function() {}; 27 | options.validate = options.validate || function() { return true }; 28 | options.submit = options.submit || function() {}; 29 | 30 | var overlay = $('
') 31 | .css("opacity", "0"); 32 | var dialog = $(''); 33 | if ($.browser.msie) { 34 | var frame = $('') 35 | .css("opacity", "0").appendTo(document.body); 36 | if (parseInt($.browser.version)<7) { 37 | dialog.css("position", "absolute"); 38 | overlay.css("position", "absolute"); 39 | $("html,body").css({width: "100%", height: "100%"}); 40 | } 41 | } 42 | overlay.appendTo(document.body).fadeTo(100, 0.6); 43 | dialog.appendTo(document.body).addClass("loading").centerBox().fadeIn(400); 44 | 45 | $(document).keydown(function(e) { 46 | if (e.keyCode == 27) dismiss(); // dismiss on escape key 47 | }); 48 | function dismiss() { 49 | dialog.fadeOut("fast", function() { 50 | $("#dialog, #overlay, #overlay-frame").remove(); 51 | }); 52 | $(document).unbind("keydown"); 53 | } 54 | overlay.click(function() { dismiss(); }); 55 | 56 | function showError(name, message) { 57 | var input = dialog.find(":input[name=" + name + "]"); 58 | input.addClass("error").next("div.error").remove(); 59 | $('
').text(message).insertAfter(input); 60 | } 61 | 62 | $.get(url, function(html) { 63 | $(html).appendTo(dialog); 64 | dialog.removeClass("loading").addClass("loaded").centerBox().each(function() { 65 | options.load(dialog.children()[0]); 66 | $(":input:first", dialog).each(function() { this.focus() }); 67 | $("button.cancel", dialog).click(function() { // dismiss on cancel 68 | dismiss(); 69 | options.cancel(); 70 | }); 71 | $("form", dialog).submit(function(e) { // invoke callback on submit 72 | e.preventDefault(); 73 | dialog.find("div.error").remove().end().find(".error").removeClass("error"); 74 | var data = {}; 75 | $.each($("form :input", dialog).serializeArray(), function(i, field) { 76 | data[field.name] = field.value; 77 | }); 78 | $("form :file", dialog).each(function() { 79 | data[this.name] = this.value; // file inputs need special handling 80 | }); 81 | options.submit(data, function callback(errors) { 82 | if ($.isEmptyObject(errors)) { 83 | dismiss(); 84 | } else { 85 | for (var name in errors) { 86 | showError(name, errors[name]); 87 | } 88 | } 89 | }); 90 | return false; 91 | }); 92 | }); 93 | }); 94 | } 95 | 96 | })(jQuery); 97 | -------------------------------------------------------------------------------- /html/js/test/view_collation.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_collation = 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 | // NOTE, the values are already in their correct sort order. Consider this 20 | // a specification of collation of json types. 21 | 22 | var values = []; 23 | 24 | // special values sort before all other types 25 | values.push(null); 26 | values.push(false); 27 | values.push(true); 28 | 29 | // then numbers 30 | values.push(1); 31 | values.push(2); 32 | values.push(3.0); 33 | values.push(4); 34 | 35 | // then text, case sensitive 36 | values.push("a"); 37 | values.push("A"); 38 | values.push("aa"); 39 | values.push("b"); 40 | values.push("B"); 41 | values.push("ba"); 42 | values.push("bb"); 43 | 44 | // then arrays. compared element by element until different. 45 | // Longer arrays sort after their prefixes 46 | values.push(["a"]); 47 | values.push(["b"]); 48 | values.push(["b","c"]); 49 | values.push(["b","c", "a"]); 50 | values.push(["b","d"]); 51 | values.push(["b","d", "e"]); 52 | 53 | // then object, compares each key value in the list until different. 54 | // larger objects sort after their subset objects. 55 | values.push({a:1}); 56 | values.push({a:2}); 57 | values.push({b:1}); 58 | values.push({b:2}); 59 | values.push({b:2, a:1}); // Member order does matter for collation. 60 | // CouchDB preserves member order 61 | // but doesn't require that clients will. 62 | // (this test might fail if used with a js engine 63 | // that doesn't preserve order) 64 | values.push({b:2, c:2}); 65 | 66 | for (var i=0; i 1 sec before the restart, the doc would likely 37 | // commit. 38 | 39 | 40 | // Retry the same thing but with full commits on. 41 | 42 | var db2 = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"true"}); 43 | 44 | T(db2.save({_id:"1",a:2,b:4}).ok); 45 | T(db2.open("1") != null); 46 | 47 | restartServer(); 48 | 49 | T(db2.open("1") != null); 50 | 51 | // You can update but without committing immediately, and then ensure 52 | // everything is commited in the last step. 53 | 54 | T(db.save({_id:"2",a:2,b:4}).ok); 55 | T(db.open("2") != null); 56 | T(db.ensureFullCommit().ok); 57 | restartServer(); 58 | 59 | T(db.open("2") != null); 60 | 61 | // However, it's possible even when flushed, that the server crashed between 62 | // the update and the commit, and you don't want to check to make sure 63 | // every doc you updated actually made it to disk. So record the instance 64 | // start time of the database before the updates and then check it again 65 | // after the flush (the instance start time is returned by the flush 66 | // operation). if they are the same, we know everything was updated 67 | // safely. 68 | 69 | // First try it with a crash. 70 | 71 | var instanceStartTime = db.info().instance_start_time; 72 | 73 | T(db.save({_id:"3",a:2,b:4}).ok); 74 | T(db.open("3") != null); 75 | 76 | restartServer(); 77 | 78 | var commitResult = db.ensureFullCommit(); 79 | T(commitResult.ok && commitResult.instance_start_time != instanceStartTime); 80 | // start times don't match, meaning the server lost our change 81 | 82 | T(db.open("3") == null); // yup lost it 83 | 84 | // retry with no server restart 85 | 86 | var instanceStartTime = db.info().instance_start_time; 87 | 88 | T(db.save({_id:"4",a:2,b:4}).ok); 89 | T(db.open("4") != null); 90 | 91 | var commitResult = db.ensureFullCommit(); 92 | T(commitResult.ok && commitResult.instance_start_time == instanceStartTime); 93 | // Successful commit, start times match! 94 | 95 | restartServer(); 96 | 97 | T(db.open("4") != null); 98 | }); 99 | 100 | // Now test that when we exceed the max_dbs_open, pending commits are safely 101 | // written. 102 | T(db.save({_id:"5",foo:"bar"}).ok); 103 | var max = 2; 104 | run_on_modified_server( 105 | [{section: "couchdb", 106 | key: "delayed_commits", 107 | value: "true"}, 108 | {section: "couchdb", 109 | key: "max_dbs_open", 110 | value: max.toString()}], 111 | 112 | function () { 113 | for(var i=0; i= 0; i -= 10) { 43 | var queryResults = db.query(queryFun, null, { 44 | startkey: i, 45 | startkey_docid: i, 46 | descending: true, 47 | limit: 10 48 | }); 49 | T(queryResults.rows.length == 10) 50 | T(queryResults.total_rows == docs.length) 51 | T(queryResults.offset == docs.length - i - 1) 52 | var j; 53 | for (j = 0; j < 10; j++) { 54 | T(queryResults.rows[j].key == i - j); 55 | } 56 | } 57 | 58 | // ignore decending=false. CouchDB should just ignore that. 59 | for (i = 0; i < docs.length; i += 10) { 60 | var queryResults = db.query(queryFun, null, { 61 | startkey: i, 62 | startkey_docid: i, 63 | descending: false, 64 | limit: 10 65 | }); 66 | T(queryResults.rows.length == 10) 67 | T(queryResults.total_rows == docs.length) 68 | T(queryResults.offset == i) 69 | var j; 70 | for (j = 0; j < 10;j++) { 71 | T(queryResults.rows[j].key == i + j); 72 | } 73 | } 74 | 75 | // test endkey_docid 76 | var queryResults = db.query(function(doc) { emit(null, null);}, null, { 77 | startkey: null, 78 | startkey_docid: 1, 79 | endkey: null, 80 | endkey_docid: 40 81 | }); 82 | 83 | T(queryResults.rows.length == 35) 84 | T(queryResults.total_rows == docs.length) 85 | T(queryResults.offset == 1) 86 | T(queryResults.rows[0].id == "1"); 87 | T(queryResults.rows[1].id == "10"); 88 | T(queryResults.rows[2].id == "11"); 89 | T(queryResults.rows[3].id == "12"); 90 | T(queryResults.rows[4].id == "13"); 91 | T(queryResults.rows[5].id == "14"); 92 | T(queryResults.rows[6].id == "15"); 93 | T(queryResults.rows[7].id == "16"); 94 | T(queryResults.rows[8].id == "17"); 95 | T(queryResults.rows[9].id == "18"); 96 | T(queryResults.rows[10].id == "19"); 97 | T(queryResults.rows[11].id == "2"); 98 | T(queryResults.rows[12].id == "20"); 99 | T(queryResults.rows[13].id == "21"); 100 | T(queryResults.rows[14].id == "22"); 101 | T(queryResults.rows[15].id == "23"); 102 | T(queryResults.rows[16].id == "24"); 103 | T(queryResults.rows[17].id == "25"); 104 | T(queryResults.rows[18].id == "26"); 105 | T(queryResults.rows[19].id == "27"); 106 | T(queryResults.rows[20].id == "28"); 107 | T(queryResults.rows[21].id == "29"); 108 | T(queryResults.rows[22].id == "3"); 109 | T(queryResults.rows[23].id == "30"); 110 | T(queryResults.rows[24].id == "31"); 111 | T(queryResults.rows[25].id == "32"); 112 | T(queryResults.rows[26].id == "33"); 113 | T(queryResults.rows[27].id == "34"); 114 | T(queryResults.rows[28].id == "35"); 115 | T(queryResults.rows[29].id == "36"); 116 | T(queryResults.rows[30].id == "37"); 117 | T(queryResults.rows[31].id == "38"); 118 | T(queryResults.rows[32].id == "39"); 119 | T(queryResults.rows[33].id == "4"); 120 | T(queryResults.rows[34].id == "40"); 121 | 122 | }; 123 | -------------------------------------------------------------------------------- /html/js/test/etags_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.etags_views = 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 designDoc = { 20 | _id:"_design/etags", 21 | language: "javascript", 22 | views : { 23 | basicView : { 24 | map : stringFun(function(doc) { 25 | emit(doc.integer, doc.string); 26 | }) 27 | }, 28 | withReduce : { 29 | map : stringFun(function(doc) { 30 | emit(doc.integer, doc.string); 31 | }), 32 | reduce : stringFun(function(keys, values, rereduce) { 33 | if (rereduce) { 34 | return sum(values); 35 | } else { 36 | return values.length; 37 | } 38 | }) 39 | } 40 | } 41 | } 42 | T(db.save(designDoc).ok); 43 | var xhr; 44 | var docs = makeDocs(0, 10); 45 | db.bulkSave(docs); 46 | 47 | // verify get w/Etag on map view 48 | xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView"); 49 | T(xhr.status == 200); 50 | var etag = xhr.getResponseHeader("etag"); 51 | xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView", { 52 | headers: {"if-none-match": etag} 53 | }); 54 | T(xhr.status == 304); 55 | // TODO GET with keys (when that is available) 56 | 57 | // reduce view 58 | xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce"); 59 | T(xhr.status == 200); 60 | var etag = xhr.getResponseHeader("etag"); 61 | xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce", { 62 | headers: {"if-none-match": etag} 63 | }); 64 | T(xhr.status == 304); 65 | 66 | // confirm ETag changes with different POST bodies 67 | xhr = CouchDB.request("POST", "/test_suite_db/_design/etags/_view/basicView", 68 | {body: JSON.stringify({keys:[1]})} 69 | ); 70 | var etag1 = xhr.getResponseHeader("etag"); 71 | xhr = CouchDB.request("POST", "/test_suite_db/_design/etags/_view/basicView", 72 | {body: JSON.stringify({keys:[2]})} 73 | ); 74 | var etag2 = xhr.getResponseHeader("etag"); 75 | T(etag1 != etag2, "POST to map view generates key-depdendent ETags"); 76 | 77 | xhr = CouchDB.request("POST", 78 | "/test_suite_db/_design/etags/_view/withReduce?group=true", 79 | {body: JSON.stringify({keys:[1]})} 80 | ); 81 | etag1 = xhr.getResponseHeader("etag"); 82 | xhr = CouchDB.request("POST", 83 | "/test_suite_db/_design/etags/_view/withReduce?group=true", 84 | {body: JSON.stringify({keys:[2]})} 85 | ); 86 | etag2 = xhr.getResponseHeader("etag"); 87 | T(etag1 != etag2, "POST to reduce view generates key-depdendent ETags"); 88 | 89 | // all docs 90 | xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 91 | T(xhr.status == 200); 92 | var etag = xhr.getResponseHeader("etag"); 93 | xhr = CouchDB.request("GET", "/test_suite_db/_all_docs", { 94 | headers: {"if-none-match": etag} 95 | }); 96 | T(xhr.status == 304); 97 | 98 | // _changes 99 | xhr = CouchDB.request("GET", "/test_suite_db/_changes"); 100 | T(xhr.status == 200); 101 | var etag = xhr.getResponseHeader("etag"); 102 | xhr = CouchDB.request("GET", "/test_suite_db/_changes", { 103 | headers: {"if-none-match": etag} 104 | }); 105 | T(xhr.status == 304); 106 | 107 | // list etag 108 | // in the list test for now 109 | 110 | // A new database should have unique _all_docs etags. 111 | db.deleteDb(); 112 | db.createDb(); 113 | db.save({a: 1}); 114 | xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 115 | var etag = xhr.getResponseHeader("etag"); 116 | db.deleteDb(); 117 | db.createDb(); 118 | db.save({a: 2}); 119 | xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 120 | var new_etag = xhr.getResponseHeader("etag"); 121 | T(etag != new_etag); 122 | // but still be cacheable 123 | xhr = CouchDB.request("GET", "/test_suite_db/_all_docs"); 124 | T(new_etag == xhr.getResponseHeader("etag")); 125 | 126 | }; 127 | -------------------------------------------------------------------------------- /html/js/test/proxyauth.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 | 14 | 15 | couchTests.proxyauth = function(debug) { 16 | // this test proxy authentification handler 17 | 18 | var usersDb = new CouchDB("test_suite_users", {"X-Couch-Full-Commit":"false"}); 19 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); 20 | 21 | if (debug) debugger; 22 | 23 | // Simple secret key generator 24 | function generateSecret(length) { 25 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 26 | var secret = ''; 27 | for (var i=0; i 2 | 3 | BrowserCouch Tests, literately 4 | 5 | 6 | 50 | 56 | 57 | 58 | 59 | 60 |

 61 | var test_data = [
 62 | 	{_id : "0", hello : 'world'},
 63 | 	{_id : "1", chunky : 'monkey'},
 64 | 	{_id : "2", foo : 'bar'},
 65 | 	{_id : "3", black : 'hat'},
 66 | 	{_id : "4", black : 'tea'},
 67 | 	{_id : "5", words : 'two foo three'},
 68 | 	{_id : "6", words: 'two'}
 69 | 	];		
 70 | 	
 71 | var db = BrowserCouch('literateTests');
 72 | 
 73 | db.onload(function(){
 74 | 	db.put(test_data, function(){});	
 75 | });
 76 | 
 77 | 
78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 100 | 101 | 102 | 103 | 104 | 105 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 137 | 138 | 139 | 140 |
Basic Database Methods
NameCodeResultExpected
GET

 91 | var db = BrowserCouch('literateTests')
 92 | db.onload(function(){
 93 | 	db.get('3', 
 94 | 		function(x){
 95 | 			result(x['black'])
 96 | 		}
 97 | 	);
 98 | });	
 99 | 
hat
PUT

106 | var db = BrowserCouch('literateTests')
107 | db.onload(function(){
108 | 	db.put({_id:'7', worked: "YES"}, 
109 | 		function(){
110 | 			db.get('7', function(x){
111 | 				result(x['worked'])
112 | 		});
113 | 			
114 | 		}	
115 | 	);
116 | });	
117 | 
YES
POST

125 | var db = BrowserCouch('literateTests')
126 | db.onload(function(){
127 | 	db.post({worked: "YES"}, 
128 | 		function(x){
129 | 			db.get(x, function(x){
130 | 				result(x['worked'])
131 | 		});
132 | 			
133 | 		}	
134 | 	);
135 | });	
136 | 
YES
141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 177 | 178 | 179 | 180 |
Database Queries
Map Reduce

155 | var db = BrowserCouch('literateTests');
156 | db.onload(function(){
157 | 	db.view({
158 | 		map : function(doc, emit){
159 | 			if (doc.words){
160 | 				var words = doc.words.split(" ");
161 |     			for (var i = 0; i < words.length; i++)
162 |       				emit(words[i], 1);
163 |       		}		
164 | 		},
165 | 		reduce : function(keys, values){
166 | 			var sum = 0;
167 |     		for (var i = 0; i < values.length; i++)
168 |       			sum += values[i];
169 |     		return sum;
170 |     	},
171 |     	finished : function(view){
172 |     		result(view.findRow('two'));
173 |     	}	
174 | 	});
175 | });	
176 | 
22
181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 210 | 211 | 212 | 213 | 214 | 215 |
Sync
Local Sync

197 | var db1 = BrowserCouch('literateTests');
198 | var db2 = BrowserCouch('literateTests2');
199 | 
200 | db2.sync('BrowserCouch:literateTests', {
201 | 	update : function(){
202 | 		db2.get('3', 
203 | 			function(x){
204 | 				result(x['black']);
205 | 			}
206 | 		);	
207 | 	}
208 | });
209 | 
hat
216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /html/js/ext/futon.format.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 | $.futon = $.futon || {}; 15 | $.extend($.futon, { 16 | 17 | // JSON pretty printing 18 | formatJSON: function(val, options) { 19 | options = $.extend({ 20 | escapeStrings: true, 21 | indent: 4, 22 | linesep: "\n", 23 | quoteKeys: true 24 | }, options || {}); 25 | var itemsep = options.linesep.length ? "," + options.linesep : ", "; 26 | 27 | function escape(string) { 28 | return string.replace(/&/g, "&") 29 | .replace(//g, ">"); 31 | } 32 | 33 | function format(val, depth) { 34 | var tab = []; 35 | for (var i = 0; i < options.indent * depth; i++) tab.push(""); 36 | tab = tab.join(" "); 37 | 38 | var type = typeof val; 39 | switch (type) { 40 | case "boolean": 41 | case "number": 42 | case "string": 43 | var retval = val; 44 | if (type == "string" && !options.escapeStrings) { 45 | retval = indentLines(retval.replace(/\r\n/g, "\n"), tab.substr(options.indent)); 46 | } else { 47 | retval = escape(JSON.stringify(val)); 48 | } 49 | if (options.html) { 50 | retval = "" + retval + ""; 51 | } 52 | return retval; 53 | 54 | case "object": { 55 | if (val === null) { 56 | if (options.html) { 57 | return "null"; 58 | } 59 | return "null"; 60 | } 61 | if (val.constructor == Date) { 62 | return JSON.stringify(val); 63 | } 64 | 65 | var buf = []; 66 | 67 | if (val.constructor == Array) { 68 | buf.push("["); 69 | for (var index = 0; index < val.length; index++) { 70 | buf.push(index > 0 ? itemsep : options.linesep); 71 | buf.push(tab, format(val[index], depth + 1)); 72 | } 73 | if (index >= 0) { 74 | buf.push(options.linesep, tab.substr(options.indent)); 75 | } 76 | buf.push("]"); 77 | if (options.html) { 78 | return "" + buf.join("") + ""; 79 | } 80 | 81 | } else { 82 | buf.push("{"); 83 | var index = 0; 84 | for (var key in val) { 85 | buf.push(index > 0 ? itemsep : options.linesep); 86 | var keyDisplay = options.quoteKeys ? JSON.stringify(key) : key; 87 | if (options.html) { 88 | if (options.quoteKeys) { 89 | keyDisplay = keyDisplay.substr(1, keyDisplay.length - 2); 90 | } 91 | keyDisplay = "" + escape(keyDisplay) + ""; 92 | if (options.quoteKeys) { 93 | keyDisplay = '"' + keyDisplay + '"'; 94 | } 95 | } 96 | buf.push(tab, keyDisplay, 97 | ": ", format(val[key], depth + 1)); 98 | index++; 99 | } 100 | if (index >= 0) { 101 | buf.push(options.linesep, tab.substr(options.indent)); 102 | } 103 | buf.push("}"); 104 | if (options.html) { 105 | return "" + buf.join("") + ""; 106 | } 107 | } 108 | 109 | return buf.join(""); 110 | } 111 | } 112 | } 113 | 114 | function indentLines(text, tab) { 115 | var lines = text.split("\n"); 116 | for (var i in lines) { 117 | lines[i] = (i > 0 ? tab : "") + escape(lines[i]); 118 | } 119 | return lines.join("
"); 120 | } 121 | 122 | return format(val, 1); 123 | }, 124 | 125 | // File size pretty printing 126 | formatSize: function(size) { 127 | var jump = 512; 128 | if (size < jump) return size + " bytes"; 129 | var units = ["KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; 130 | var i = 0; 131 | while (size >= jump && i < units.length) { 132 | i += 1; 133 | size /= 1024 134 | } 135 | return size.toFixed(1) + ' ' + units[i - 1]; 136 | } 137 | 138 | }); 139 | 140 | })(jQuery); 141 | -------------------------------------------------------------------------------- /html/js/test/erlang_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.erlang_views = 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 | 21 | run_on_modified_server( 22 | [{section: "native_query_servers", 23 | key: "erlang", 24 | value: "{couch_native_process, start_link, []}"}], 25 | function() { 26 | // Note we just do some basic 'smoke tests' here - the 27 | // test/query_server_spec.rb tests have more comprehensive tests 28 | var doc = {_id: "1", integer: 1, string: "str1", array: [1, 2, 3]}; 29 | T(db.save(doc).ok); 30 | 31 | var mfun = 'fun({Doc}) -> ' + 32 | ' K = proplists:get_value(<<"integer">>, Doc, null), ' + 33 | ' V = proplists:get_value(<<"string">>, Doc, null), ' + 34 | ' Emit(K, V) ' + 35 | 'end.'; 36 | 37 | // emitting a key value that is undefined should result in that row not 38 | // being included in the view results 39 | var results = db.query(mfun, null, null, null, "erlang"); 40 | T(results.total_rows == 1); 41 | T(results.rows[0].key == 1); 42 | T(results.rows[0].value == "str1"); 43 | 44 | // check simple reduction - another doc with same key. 45 | var doc = {_id: "2", integer: 1, string: "str2"}; 46 | T(db.save(doc).ok); 47 | rfun = "fun(Keys, Values, ReReduce) -> length(Values) end." 48 | results = db.query(mfun, rfun, null, null, "erlang"); 49 | T(results.rows[0].value == 2); 50 | 51 | // simple 'list' tests 52 | var designDoc = { 53 | _id:"_design/erlview", 54 | language: "erlang", 55 | shows: { 56 | simple: 57 | 'fun(Doc, {Req}) -> ' + 58 | ' {Info} = proplists:get_value(<<"info">>, Req, {[]}), ' + 59 | ' Purged = proplists:get_value(<<"purge_seq">>, Info, -1), ' + 60 | ' Verb = proplists:get_value(<<"method">>, Req, <<"not_get">>), ' + 61 | ' R = list_to_binary(io_lib:format("~b - ~s", [Purged, Verb])), ' + 62 | ' {[{<<"code">>, 200}, {<<"headers">>, {[]}}, {<<"body">>, R}]} ' + 63 | 'end.' 64 | }, 65 | lists: { 66 | simple_list : 67 | 'fun(Head, {Req}) -> ' + 68 | ' Send(<<"head">>), ' + 69 | ' Fun = fun({Row}, _) -> ' + 70 | ' Val = proplists:get_value(<<"value">>, Row, -1), ' + 71 | ' Send(list_to_binary(integer_to_list(Val))), ' + 72 | ' {ok, nil} ' + 73 | ' end, ' + 74 | ' {ok, _} = FoldRows(Fun, nil), ' + 75 | ' <<"tail">> ' + 76 | 'end. ' 77 | }, 78 | views: { 79 | simple_view : { 80 | map: mfun, 81 | reduce: rfun 82 | } 83 | } 84 | }; 85 | T(db.save(designDoc).ok); 86 | 87 | var url = "/test_suite_db/_design/erlview/_show/simple/1"; 88 | var xhr = CouchDB.request("GET", url); 89 | T(xhr.status == 200, "standard get should be 200"); 90 | T(xhr.responseText == "0 - GET"); 91 | 92 | var url = "/test_suite_db/_design/erlview/_list/simple_list/simple_view"; 93 | var xhr = CouchDB.request("GET", url); 94 | T(xhr.status == 200, "standard get should be 200"); 95 | T(xhr.responseText == "head2tail"); 96 | 97 | // Larger dataset 98 | 99 | db.deleteDb(); 100 | db.createDb(); 101 | var words = "foo bar abc def baz xxyz".split(/\s+/); 102 | 103 | var docs = []; 104 | for(var i = 0; i < 250; i++) { 105 | var body = []; 106 | for(var j = 0; j < 100; j++) { 107 | body.push({ 108 | word: words[j%words.length], 109 | count: j 110 | }); 111 | } 112 | docs.push({ 113 | "_id": "test-" + i, 114 | "words": body 115 | }); 116 | } 117 | T(db.bulkSave(docs).length, 250, "Saved big doc set."); 118 | 119 | var mfun = 'fun({Doc}) -> ' + 120 | 'Words = proplists:get_value(<<"words">>, Doc), ' + 121 | 'lists:foreach(fun({Word}) -> ' + 122 | 'WordString = proplists:get_value(<<"word">>, Word), ' + 123 | 'Count = proplists:get_value(<<"count">>, Word), ' + 124 | 'Emit(WordString , Count) ' + 125 | 'end, Words) ' + 126 | 'end.'; 127 | 128 | var rfun = 'fun(Keys, Values, RR) -> length(Values) end.'; 129 | var results = db.query(mfun, rfun, null, null, "erlang"); 130 | T(results.rows[0].key === null, "Returned a reduced value."); 131 | T(results.rows[0].value > 0, "Reduce value exists."); 132 | }); 133 | }; 134 | -------------------------------------------------------------------------------- /html/js/test/reduce_builtin.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_builtin = 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 = 500 20 | var docs = makeDocs(1,numDocs + 1); 21 | db.bulkSave(docs); 22 | 23 | var summate = function(N) {return (N+1)*N/2;}; 24 | 25 | var sumsqr = function(N) { 26 | var acc = 0; 27 | for (var i=1; i<=N; ++i) { 28 | acc += i*i; 29 | } 30 | return acc; 31 | } 32 | 33 | // this is the same test as the reduce.js test 34 | // only we'll let CouchDB run reduce in Erlang 35 | var map = function (doc) { 36 | emit(doc.integer, doc.integer); 37 | emit(doc.integer, doc.integer)}; 38 | 39 | var result = db.query(map, "_sum"); 40 | T(result.rows[0].value == 2*summate(numDocs)); 41 | result = db.query(map, "_count"); 42 | T(result.rows[0].value == 1000); 43 | result = db.query(map, "_stats"); 44 | T(result.rows[0].value.sum == 2*summate(numDocs)); 45 | T(result.rows[0].value.count == 1000); 46 | T(result.rows[0].value.min == 1); 47 | T(result.rows[0].value.max == 500); 48 | T(result.rows[0].value.sumsqr == 2*sumsqr(numDocs)); 49 | 50 | result = db.query(map, "_sum", {startkey: 4, endkey: 4}); 51 | T(result.rows[0].value == 8); 52 | result = db.query(map, "_count", {startkey: 4, endkey: 4}); 53 | T(result.rows[0].value == 2); 54 | 55 | result = db.query(map, "_sum", {startkey: 4, endkey: 5}); 56 | T(result.rows[0].value == 18); 57 | result = db.query(map, "_count", {startkey: 4, endkey: 5}); 58 | T(result.rows[0].value == 4); 59 | 60 | result = db.query(map, "_sum", {startkey: 4, endkey: 6}); 61 | T(result.rows[0].value == 30); 62 | result = db.query(map, "_count", {startkey: 4, endkey: 6}); 63 | T(result.rows[0].value == 6); 64 | 65 | result = db.query(map, "_sum", {group:true, limit:3}); 66 | T(result.rows[0].value == 2); 67 | T(result.rows[1].value == 4); 68 | T(result.rows[2].value == 6); 69 | 70 | for(var i=1; iNew World

"]; 35 | }; 36 | // 37 | return [null, "

Empty World

"]; 38 | }; 39 | // we can update the document inline 40 | doc.world = "hello"; 41 | // we can record aspects of the request or use them in application logic. 42 | doc.reqs && doc.reqs.push(req); 43 | doc.edited_by = req.userCtx; 44 | return [doc, "

hello doc

"]; 45 | }), 46 | "in-place" : stringFun(function(doc, req) { 47 | var field = req.query.field; 48 | var value = req.query.value; 49 | var message = "set "+field+" to "+value; 50 | doc[field] = value; 51 | return [doc, message]; 52 | }), 53 | "bump-counter" : stringFun(function(doc, req) { 54 | if (!doc.counter) doc.counter = 0; 55 | doc.counter += 1; 56 | var message = "

bumped it!

"; 57 | return [doc, message]; 58 | }), 59 | "error" : stringFun(function(doc, req) { 60 | superFail.badCrash; 61 | }), 62 | "xml" : stringFun(function(doc, req) { 63 | var xml = new XML(''); 64 | xml.title = doc.title; 65 | var posted_xml = new XML(req.body); 66 | doc.via_xml = posted_xml.foo.toString(); 67 | var resp = { 68 | "headers" : { 69 | "Content-Type" : "application/xml" 70 | }, 71 | "body" : xml.toXMLString() 72 | }; 73 | 74 | return [doc, resp]; 75 | }) 76 | } 77 | }; 78 | T(db.save(designDoc).ok); 79 | 80 | var doc = {"word":"plankton", "name":"Rusty"} 81 | var resp = db.save(doc); 82 | T(resp.ok); 83 | var docid = resp.id; 84 | 85 | // update error 86 | var xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/"); 87 | T(xhr.status == 404, 'Should be missing'); 88 | T(JSON.parse(xhr.responseText).reason == "Invalid path."); 89 | 90 | // hello update world 91 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/hello/"+docid); 92 | T(xhr.status == 201); 93 | T(xhr.responseText == "

hello doc

"); 94 | T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type"))) 95 | 96 | doc = db.open(docid); 97 | T(doc.world == "hello"); 98 | 99 | // Fix for COUCHDB-379 100 | T(equals(xhr.getResponseHeader("Server").substr(0,7), "CouchDB")); 101 | 102 | // hello update world (no docid) 103 | xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/hello"); 104 | T(xhr.status == 200); 105 | T(xhr.responseText == "

Empty World

"); 106 | 107 | // no GET allowed 108 | xhr = CouchDB.request("GET", "/test_suite_db/_design/update/_update/hello"); 109 | // T(xhr.status == 405); // TODO allow qs to throw error code as well as error message 110 | T(JSON.parse(xhr.responseText).error == "method_not_allowed"); 111 | 112 | // // hello update world (non-existing docid) 113 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/hello/nonExistingDoc"); 114 | T(xhr.status == 201); 115 | T(xhr.responseText == "

New World

"); 116 | 117 | // in place update 118 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/in-place/"+docid+'?field=title&value=test'); 119 | T(xhr.status == 201); 120 | T(xhr.responseText == "set title to test"); 121 | doc = db.open(docid); 122 | T(doc.title == "test"); 123 | 124 | // bump counter 125 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/bump-counter/"+docid, { 126 | headers : {"X-Couch-Full-Commit":"false"} 127 | }); 128 | T(xhr.status == 201); 129 | T(xhr.responseText == "

bumped it!

"); 130 | doc = db.open(docid); 131 | T(doc.counter == 1); 132 | 133 | // _update honors full commit if you need it to 134 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/bump-counter/"+docid, { 135 | headers : {"X-Couch-Full-Commit":"true"} 136 | }); 137 | 138 | doc = db.open(docid); 139 | T(doc.counter == 2); 140 | 141 | // parse xml 142 | xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/xml/"+docid, { 143 | headers : {"X-Couch-Full-Commit":"false"}, 144 | "body" : 'bar' 145 | }); 146 | T(xhr.status == 201); 147 | T(xhr.responseText == "\n test\n"); 148 | 149 | doc = db.open(docid); 150 | T(doc.via_xml == "bar"); 151 | 152 | }; 153 | -------------------------------------------------------------------------------- /html/js/test/attachment_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.attachment_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 | // first just save a regular doc with an attachment that has a slash in the url. 23 | // (also gonna run an encoding check case) 24 | var binAttDoc = { 25 | _id: "bin_doc", 26 | _attachments:{ 27 | "foo/bar.txt": { 28 | content_type:"text/plain", 29 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" 30 | }, 31 | "foo%2Fbaz.txt": { 32 | content_type:"text/plain", 33 | data: "V2UgbGlrZSBwZXJjZW50IHR3byBGLg==" 34 | } 35 | } 36 | } 37 | 38 | T(db.save(binAttDoc).ok); 39 | 40 | var xhr = CouchDB.request("GET", "/"+dbName+"/bin_doc/foo/bar.txt"); 41 | T(xhr.responseText == "This is a base64 encoded text"); 42 | T(xhr.getResponseHeader("Content-Type") == "text/plain"); 43 | 44 | // lets try it with an escaped attachment id... 45 | // weird that it's at two urls 46 | var xhr = CouchDB.request("GET", "/"+dbName+"/bin_doc/foo%2Fbar.txt"); 47 | T(xhr.status == 200); 48 | // xhr.responseText == "This is a base64 encoded text" 49 | 50 | var xhr = CouchDB.request("GET", "/"+dbName+"/bin_doc/foo/baz.txt"); 51 | T(xhr.status == 404); 52 | 53 | var xhr = CouchDB.request("GET", "/"+dbName+"/bin_doc/foo%252Fbaz.txt"); 54 | T(xhr.status == 200); 55 | T(xhr.responseText == "We like percent two F."); 56 | 57 | // require a _rev to PUT 58 | var xhr = CouchDB.request("PUT", "/"+dbName+"/bin_doc/foo/attachment.txt", { 59 | headers:{"Content-Type":"text/plain;charset=utf-8"}, 60 | body:"Just some text" 61 | }); 62 | T(xhr.status == 409); 63 | 64 | var xhr = CouchDB.request("PUT", "/"+dbName+"/bin_doc/foo/bar2.txt?rev=" + binAttDoc._rev, { 65 | body:"This is no base64 encoded text", 66 | headers:{"Content-Type": "text/plain;charset=utf-8"} 67 | }); 68 | T(xhr.status == 201); 69 | var rev = JSON.parse(xhr.responseText).rev; 70 | 71 | binAttDoc = db.open("bin_doc"); 72 | 73 | T(binAttDoc._attachments["foo/bar.txt"] !== undefined); 74 | T(binAttDoc._attachments["foo%2Fbaz.txt"] !== undefined); 75 | T(binAttDoc._attachments["foo/bar2.txt"] !== undefined); 76 | T(binAttDoc._attachments["foo/bar2.txt"].content_type == "text/plain;charset=utf-8"); 77 | T(binAttDoc._attachments["foo/bar2.txt"].length == 30); 78 | 79 | //// now repeat the while thing with a design doc 80 | 81 | // first just save a regular doc with an attachment that has a slash in the url. 82 | // (also gonna run an encoding check case) 83 | var binAttDoc = { 84 | _id: "_design/bin_doc", 85 | _attachments:{ 86 | "foo/bar.txt": { 87 | content_type:"text/plain", 88 | data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" 89 | }, 90 | "foo%2Fbaz.txt": { 91 | content_type:"text/plain", 92 | data: "V2UgbGlrZSBwZXJjZW50IHR3byBGLg==" 93 | } 94 | } 95 | } 96 | 97 | T(db.save(binAttDoc).ok); 98 | 99 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Fbin_doc/foo/bar.txt"); 100 | T(xhr.responseText == "This is a base64 encoded text"); 101 | T(xhr.getResponseHeader("Content-Type") == "text/plain"); 102 | 103 | // lets try it with an escaped attachment id... 104 | // weird that it's at two urls 105 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Fbin_doc/foo%2Fbar.txt"); 106 | T(xhr.responseText == "This is a base64 encoded text"); 107 | T(xhr.status == 200); 108 | 109 | // err, 3 urls 110 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design/bin_doc/foo%2Fbar.txt"); 111 | T(xhr.responseText == "This is a base64 encoded text"); 112 | T(xhr.status == 200); 113 | 114 | // I mean um, 4 urls 115 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design/bin_doc/foo/bar.txt"); 116 | T(xhr.responseText == "This is a base64 encoded text"); 117 | T(xhr.status == 200); 118 | 119 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Fbin_doc/foo/baz.txt"); 120 | T(xhr.status == 404); 121 | 122 | var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Fbin_doc/foo%252Fbaz.txt"); 123 | T(xhr.status == 200); 124 | T(xhr.responseText == "We like percent two F."); 125 | 126 | // require a _rev to PUT 127 | var xhr = CouchDB.request("PUT", "/"+dbName+"/_design%2Fbin_doc/foo/attachment.txt", { 128 | headers:{"Content-Type":"text/plain;charset=utf-8"}, 129 | body:"Just some text" 130 | }); 131 | T(xhr.status == 409); 132 | 133 | var xhr = CouchDB.request("PUT", "/"+dbName+"/_design%2Fbin_doc/foo/bar2.txt?rev=" + binAttDoc._rev, { 134 | body:"This is no base64 encoded text", 135 | headers:{"Content-Type": "text/plain;charset=utf-8"} 136 | }); 137 | T(xhr.status == 201); 138 | var rev = JSON.parse(xhr.responseText).rev; 139 | 140 | binAttDoc = db.open("_design/bin_doc"); 141 | 142 | T(binAttDoc._attachments["foo/bar.txt"] !== undefined); 143 | T(binAttDoc._attachments["foo/bar2.txt"] !== undefined); 144 | T(binAttDoc._attachments["foo/bar2.txt"].content_type == "text/plain;charset=utf-8"); 145 | T(binAttDoc._attachments["foo/bar2.txt"].length == 30); 146 | } 147 | }; 148 | -------------------------------------------------------------------------------- /html/js/test/view_errors.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_errors = function(debug) { 14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"true"}); 15 | db.deleteDb(); 16 | db.createDb(); 17 | if (debug) debugger; 18 | 19 | run_on_modified_server( 20 | [{section: "couchdb", 21 | key: "os_process_timeout", 22 | value: "500"}], 23 | function() { 24 | var doc = {integer: 1, string: "1", array: [1, 2, 3]}; 25 | T(db.save(doc).ok); 26 | 27 | // emitting a key value that is undefined should result in that row 28 | // being included in the view results as null 29 | var results = db.query(function(doc) { 30 | emit(doc.undef, null); 31 | }); 32 | T(results.total_rows == 1); 33 | T(results.rows[0].key == null); 34 | 35 | // if a view function throws an exception, its results are not included in 36 | // the view index, but the view does not itself raise an error 37 | var results = db.query(function(doc) { 38 | doc.undef(); // throws an error 39 | }); 40 | T(results.total_rows == 0); 41 | 42 | // if a view function includes an undefined value in the emitted key or 43 | // value, it is treated as null 44 | var results = db.query(function(doc) { 45 | emit([doc._id, doc.undef], null); 46 | }); 47 | T(results.total_rows == 1); 48 | T(results.rows[0].key[1] == null); 49 | 50 | // querying a view with invalid params should give a resonable error message 51 | var xhr = CouchDB.request("POST", "/test_suite_db/_temp_view?startkey=foo", { 52 | headers: {"Content-Type": "application/json"}, 53 | body: JSON.stringify({language: "javascript", 54 | map : "function(doc){emit(doc.integer)}" 55 | }) 56 | }); 57 | T(JSON.parse(xhr.responseText).error == "bad_request"); 58 | 59 | // views should ignore Content-Type, like the rest of CouchDB 60 | var xhr = CouchDB.request("POST", "/test_suite_db/_temp_view", { 61 | headers: {"Content-Type": "application/x-www-form-urlencoded"}, 62 | body: JSON.stringify({language: "javascript", 63 | map : "function(doc){}" 64 | }) 65 | }); 66 | T(xhr.status == 200); 67 | 68 | var map = function (doc) {emit(doc.integer, doc.integer);}; 69 | 70 | try { 71 | db.query(map, null, {group: true}); 72 | T(0 == 1); 73 | } catch(e) { 74 | T(e.error == "query_parse_error"); 75 | } 76 | 77 | // reduce=false on map views doesn't work, so group=true will 78 | // never throw for temp reduce views. 79 | 80 | var designDoc = { 81 | _id:"_design/test", 82 | language: "javascript", 83 | views: { 84 | "no_reduce": {map:"function(doc) {emit(doc._id, null);}"}, 85 | "with_reduce": { 86 | map:"function (doc) {emit(doc.integer, doc.integer)};", 87 | reduce:"function (keys, values) { return sum(values); };"} 88 | } 89 | }; 90 | T(db.save(designDoc).ok); 91 | 92 | var designDoc2 = { 93 | _id:"_design/testbig", 94 | language: "javascript", 95 | views: { 96 | "reduce_too_big" : { 97 | map:"function (doc) {emit(doc.integer, doc.integer)};", 98 | reduce:"function (keys, values) { var chars = []; for (var i=0; i < 1000; i++) {chars.push('wazzap');};return chars; };"} 99 | } 100 | }; 101 | T(db.save(designDoc2).ok); 102 | 103 | try { 104 | db.view("test/no_reduce", {group: true}); 105 | T(0 == 1); 106 | } catch(e) { 107 | T(e.error == "query_parse_error"); 108 | } 109 | 110 | try { 111 | db.view("test/no_reduce", {reduce: true}); 112 | T(0 == 1); 113 | } catch(e) { 114 | T(db.last_req.status == 400); 115 | T(e.error == "query_parse_error"); 116 | } 117 | 118 | try { 119 | db.view("test/with_reduce", {group: true, reduce: false}); 120 | T(0 == 1); 121 | } catch(e) { 122 | T(e.error == "query_parse_error"); 123 | } 124 | 125 | var designDoc3 = { 126 | _id:"_design/infinite", 127 | language: "javascript", 128 | views: { 129 | "infinite_loop" :{map:"function(doc) {while(true){emit(doc,doc);}};"} 130 | } 131 | }; 132 | T(db.save(designDoc3).ok); 133 | 134 | try { 135 | db.view("infinite/infinite_loop"); 136 | T(0 == 1); 137 | } catch(e) { 138 | T(e.error == "os_process_error"); 139 | } 140 | 141 | // Check error responses for invalid multi-get bodies. 142 | var path = "/test_suite_db/_design/test/_view/no_reduce"; 143 | var xhr = CouchDB.request("POST", path, {body: "[]"}); 144 | T(xhr.status == 400); 145 | result = JSON.parse(xhr.responseText); 146 | T(result.error == "bad_request"); 147 | T(result.reason == "Request body must be a JSON object"); 148 | var data = "{\"keys\": 1}"; 149 | xhr = CouchDB.request("POST", path, {body:data}); 150 | T(xhr.status == 400); 151 | result = JSON.parse(xhr.responseText); 152 | T(result.error == "bad_request"); 153 | T(result.reason == "`keys` member must be a array."); 154 | 155 | // if the reduce grows to fast, throw an overflow error 156 | var path = "/test_suite_db/_design/testbig/_view/reduce_too_big"; 157 | xhr = CouchDB.request("GET", path); 158 | T(xhr.status == 500); 159 | result = JSON.parse(xhr.responseText); 160 | T(result.error == "reduce_overflow_error"); 161 | }); 162 | }; 163 | -------------------------------------------------------------------------------- /html/js/test/design_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.design_docs = function(debug) { 14 | var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); 15 | var db2 = new CouchDB("test_suite_db_a", {"X-Couch-Full-Commit":"false"}); 16 | db.deleteDb(); 17 | db.createDb(); 18 | db2.deleteDb(); 19 | db2.createDb(); 20 | if (debug) debugger; 21 | 22 | run_on_modified_server( 23 | [{section: "query_server_config", 24 | key: "reduce_limit", 25 | value: "false"}], 26 | function() { 27 | 28 | var numDocs = 500; 29 | 30 | function makebigstring(power) { 31 | var str = "a"; 32 | while(power-- > 0) { 33 | str = str + str; 34 | } 35 | return str; 36 | } 37 | 38 | var designDoc = { 39 | _id:"_design/test", // turn off couch.js id escaping? 40 | language: "javascript", 41 | whatever : { 42 | stringzone : "exports.string = 'plankton';", 43 | commonjs : { 44 | whynot : "exports.test = require('../stringzone')", 45 | upper : "exports.testing = require('./whynot').test.string.toUpperCase()" 46 | } 47 | }, 48 | views: { 49 | all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"}, 50 | no_docs: {map: "function(doc) {}"}, 51 | single_doc: {map: "function(doc) { if (doc._id == \"1\") { emit(1, null) }}"}, 52 | summate: {map:"function (doc) {emit(doc.integer, doc.integer)};", 53 | reduce:"function (keys, values) { return sum(values); };"}, 54 | summate2: {map:"function (doc) {emit(doc.integer, doc.integer)};", 55 | reduce:"function (keys, values) { return sum(values); };"}, 56 | huge_src_and_results: {map: "function(doc) { if (doc._id == \"1\") { emit(\"" + makebigstring(16) + "\", null) }}", 57 | reduce:"function (keys, values) { return \"" + makebigstring(16) + "\"; };"} 58 | }, 59 | shows: { 60 | simple: "function() {return 'ok'};", 61 | requirey : "function() { var lib = require('whatever/commonjs/upper'); return lib.testing; };" 62 | } 63 | }; 64 | 65 | var xhr = CouchDB.request("PUT", "/test_suite_db_a/_design/test", {body: JSON.stringify(designDoc)}); 66 | var resp = JSON.parse(xhr.responseText); 67 | 68 | TEquals(resp.rev, db.save(designDoc).rev); 69 | 70 | // test that editing a show fun on the ddoc results in a change in output 71 | var xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_show/simple"); 72 | T(xhr.status == 200); 73 | TEquals(xhr.responseText, "ok"); 74 | 75 | designDoc.shows.simple = "function() {return 'ko'};" 76 | T(db.save(designDoc).ok); 77 | 78 | var xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_show/simple"); 79 | T(xhr.status == 200); 80 | TEquals(xhr.responseText, "ko"); 81 | 82 | var xhr = CouchDB.request("GET", "/test_suite_db_a/_design/test/_show/simple?cache=buster"); 83 | T(xhr.status == 200); 84 | TEquals("ok", xhr.responseText, 'query server used wrong ddoc'); 85 | 86 | // test commonjs require 87 | var xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_show/requirey"); 88 | T(xhr.status == 200); 89 | TEquals("PLANKTON", xhr.responseText); 90 | 91 | // test that we get design doc info back 92 | var dinfo = db.designInfo("_design/test"); 93 | TEquals("test", dinfo.name); 94 | var vinfo = dinfo.view_index; 95 | TEquals(51, vinfo.disk_size); 96 | TEquals(false, vinfo.compact_running); 97 | TEquals("3f88e53b303e2342e49a66c538c30679", vinfo.signature); 98 | 99 | db.bulkSave(makeDocs(1, numDocs + 1)); 100 | 101 | // test that the _all_docs view returns correctly with keys 102 | var results = db.allDocs({startkey:"_design", endkey:"_design0"}); 103 | T(results.rows.length == 1); 104 | 105 | for (var loop = 0; loop < 2; loop++) { 106 | var rows = db.view("test/all_docs_twice").rows; 107 | for (var i = 0; i < numDocs; i++) { 108 | T(rows[2*i].key == i+1); 109 | T(rows[(2*i)+1].key == i+1); 110 | } 111 | T(db.view("test/no_docs").total_rows == 0) 112 | T(db.view("test/single_doc").total_rows == 1) 113 | T(db.ensureFullCommit().ok); 114 | restartServer(); 115 | }; 116 | 117 | // test when language not specified, Javascript is implied 118 | var designDoc2 = { 119 | _id:"_design/test2", 120 | // language: "javascript", 121 | views: { 122 | single_doc: {map: "function(doc) { if (doc._id == \"1\") { emit(1, null) }}"} 123 | } 124 | }; 125 | 126 | T(db.save(designDoc2).ok); 127 | T(db.view("test2/single_doc").total_rows == 1); 128 | 129 | var summate = function(N) {return (N+1)*N/2;}; 130 | var result = db.view("test/summate"); 131 | T(result.rows[0].value == summate(numDocs)); 132 | 133 | result = db.view("test/summate", {startkey:4,endkey:4}); 134 | T(result.rows[0].value == 4); 135 | 136 | result = db.view("test/summate", {startkey:4,endkey:5}); 137 | T(result.rows[0].value == 9); 138 | 139 | result = db.view("test/summate", {startkey:4,endkey:6}); 140 | T(result.rows[0].value == 15); 141 | 142 | // Verify that a shared index (view def is an exact copy of "summate") 143 | // does not confuse the reduce stage 144 | result = db.view("test/summate2", {startkey:4,endkey:6}); 145 | T(result.rows[0].value == 15); 146 | 147 | for(var i=1; i