// Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // couch.js, with modifications // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // some monkeypatches var JSON = { parse : function(string) { return eval('('+string+')'); }, stringify : function(obj) { return toJSON(obj||null); } }; RegExp.escape = function(text) { if (!arguments.callee.sRE) { var specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ]; arguments.callee.sRE = new RegExp( '(\\' + specials.join('|\\') + ')', 'g' ); } return text.replace(arguments.callee.sRE, '\\$1'); } // This is a JS wrapper for the curl function made available in couch_js.c, // it should be used in other JavaScripts that would like to make HTTP calls. var HTTP = (function() { function parseCurl(string) { var parts = string.split(/\r\n\r\n/); var body = parts.pop(); var header = parts.pop(); var headers = header.split(/\n/); var status = /HTTP\/1.\d (\d*)/.exec(header)[1]; return { responseText: body, status: parseInt(status), getResponseHeader: function(key) { var keymatcher = new RegExp(RegExp.escape(key), "i"); for (var i in headers) { var h = headers[i]; if (keymatcher.test(h)) { var value = h.substr(key.length+2); return value.replace(/^\s+|\s+$/g,""); } } return ""; } } }; return { GET : function(url, body, headers) { var st, urx = url, hx = (headers || null); st = gethttp(urx, hx); return parseCurl(st); }, HEAD : function(url, body, headers) { var st, urx = url, hx = (headers || null); st = headhttp(urx, hx); return parseCurl(st); }, DELETE : function(url, body, headers) { var st, urx = url, hx = (headers || null); st = delhttp(urx, hx); return parseCurl(st); }, MOVE : function(url, body, headers) { var st, urx = url, hx = (headers || null); st = movehttp(urx, hx); return parseCurl(st); }, COPY : function(url, body, headers) { var st, urx = url, hx = (headers || null); st = copyhttp(urx, hx); return parseCurl(st); }, POST : function(url, body, headers) { var st, urx = url, bx = (body || ""), hx = (headers || {}); hx['Content-Type'] = hx['Content-Type'] || "application/json"; st = posthttp(urx, bx, hx); return parseCurl(st); }, PUT : function(url, body, headers) { var st, urx = url, bx = (body || ""), hx = (headers || {}); hx['Content-Type'] = hx['Content-Type'] || "application/json"; st = puthttp(urx, bx, hx); return parseCurl(st); } }; })(); // Monkeypatches to CouchDB client for use of curl. CouchDB.host = (typeof window == 'undefined' || !window) ? "127.0.0.1:5984" : window; CouchDB.request = function(method, uri, options) { var full_uri = "http://" + CouchDB.host + uri; options = options || {}; var response = HTTP[method](full_uri, options.body, options.headers); return response; } function toJSON(val) { if (typeof(val) == "undefined") { throw {error:"bad_value", reason:"Cannot encode 'undefined' value as JSON"}; } var subs = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; if (typeof(val) == "xml") { // E4X support val = val.toXMLString(); } return { "Array": function(v) { var buf = []; for (var i = 0; i < v.length; i++) { buf.push(toJSON(v[i])); } return "[" + buf.join(",") + "]"; }, "Boolean": function(v) { return v.toString(); }, "Date": function(v) { var f = function(n) { return n < 10 ? '0' + n : n } return '"' + v.getUTCFullYear() + '-' + f(v.getUTCMonth() + 1) + '-' + f(v.getUTCDate()) + 'T' + f(v.getUTCHours()) + ':' + f(v.getUTCMinutes()) + ':' + f(v.getUTCSeconds()) + 'Z"'; }, "Number": function(v) { return isFinite(v) ? v.toString() : "null"; }, "Object": function(v) { if (v === null) return "null"; var buf = []; for (var k in v) { if (!v.hasOwnProperty(k) || typeof(k) !== "string" || v[k] === undefined) { continue; } buf.push(toJSON(k, val) + ": " + toJSON(v[k])); } return "{" + buf.join(",") + "}"; }, "String": function(v) { if (/["\\\x00-\x1f]/.test(v)) { v = v.replace(/([\x00-\x1f\\"])/g, function(a, b) { var c = subs[b]; if (c) return c; c = b.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); }); } return '"' + v + '"'; } }[val != null ? val.constructor.name : "Object"](val); } // *************** Test Framework Console Adapter ****************** // var p = print; var numFailures = 0; function runAllTestsConsole() { var numTests = 0; var debug = false; for (var t in couchTests) { p(t); if (t == "utf8") { p("We skip the utf8 test because it fails due to problems in couch_js.c"); p("Run the in-browser tests to verify utf8.\n"); } else { numTests += 1; var testFun = couchTests[t]; runTestConsole(testFun, debug); } } p("Results: "+numFailures.toString() + " failures in "+numTests+" tests.") }; function runTestConsole(testFun, debug) { var start = new Date().getTime(); try { if (!debug) testFun = patchTest(testFun) || testFun; testFun(); p("PASS"); } catch(e) { p("ERROR"); p("Exception raised: "+e.toString()); p("Backtrace: "+e.stack); } var duration = new Date().getTime() - start; p(duration+"ms\n"); }; // Use T to perform a test that returns false on failure and if the test fails, // display the line that failed. // Example: // T(MyValue==1); function T(arg1, arg2) { if (!arg1) { p("Assertion failed: "+(arg2 != null ? arg2 : arg1).toString()); numFailures += 1 } } p("Running CouchDB Test Suite\n"); p("Host: "+CouchDB.host); try { p("Version: "+CouchDB.getVersion()+"\n"); runAllTestsConsole(); // runTestConsole(tests.attachments); } catch (e) { p(e.toString()); } p("\nFinished");