diff --git a/source/.gitignore b/source/.gitignore
index 7e4fa3b..392f358 100644
--- a/source/.gitignore
+++ b/source/.gitignore
@@ -1,8 +1,5 @@
*.csproj
-*.njsproj
-generateDocs.cmd
-RunFunctionalTests.cmd
-runtests.cmd
+*.cmd
config.js
.vs/
diff --git a/source/DocumentDB.njsproj b/source/DocumentDB.Node.master.njsproj
similarity index 74%
rename from source/DocumentDB.njsproj
rename to source/DocumentDB.Node.master.njsproj
index 9ffcebe..3df083e 100644
--- a/source/DocumentDB.njsproj
+++ b/source/DocumentDB.Node.master.njsproj
@@ -3,24 +3,24 @@
+ This project provides a node module that makes it easy to interact with Azure DocumentDB. For documentation please see the Microsoft Azure DocumentDB Node.js SDK Documentation.
+ The core module uses the callbacks model for responses, exposed through the DocumentClient To use this SDK to call Azure DocumentDB, you need to first create an account. You can follow this tutorial to help you get started.
- DocumentDB is a purpose built NoSQL JSON document database designed for modern mobile and web applications. DocumentDB supports rich queries over JSON data as well as,
- The Nodejs sdk uses callbacks model for responses and this is exposed in DocumentClient Windows Azure DocumentDB Node.js SDK
+ Installation
Core Module
+ npm install documentdb
Usage
+ Examples
Hello World using Callbacks via the Core Module
+
+
+
diff --git a/source/readme.md b/source/readme.md
deleted file mode 100644
index 214a534..0000000
--- a/source/readme.md
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
- var DocumentClient = require('documentdb').DocumentClient;
+var host = "[hostendpoint]"; // Add your endpoint
+var masterKey = "[database account masterkey]"; // Add the massterkey of the endpoint
+var client = new DocumentClient(host, {masterKey: masterKey});
+var databaseDefinition = { id: "sample database" };
+var collectionDefinition = { id: "sample collection" };
+var documentDefinition = { id: "hello world doc", content: "Hello World!" };
+client.createDatabase(databaseDefinition, function(err, database) {
+ if(err) return console.log(err);
+ console.log('created db');
+ client.createCollection(database._self, collectionDefinition, function(err, collection) {
+ if(err) return console.log(err);
+ console.log('created collection');
+ client.createDocument(collection._self, documentDefinition, function(err, document) {
+ if(err) return console.log(err);
+ console.log('Created Document with content: ', document.content);
+ cleanup(client, database);
+ });
+ });
+});
+function cleanup(client, database) {
+ client.deleteDatabase(database._self, function(err) {
+ if(err) console.log(err);
+ })
+}
Windows Azure DocumentDB nodejs SDK
-
- transactional execution of JavaScript based application logic. DocumentDB is built with a deep commitment to the JSON data model enabling it to offer differentiated query and data
- processing capabilities that scale to meet the needs of the most demanding modern applications.
-
- Installing the library using npm
- > npm install documentdb
- -var DocumentClient = require('documentdb').DocumentClient; - -var host = [hostendpoint]; // Add your endpoint -var masterKey = [database account masterkey]; // Add the massterkey of the endpoint - -var client = new DocumentClient(host, {masterKey: masterKey}); -var databaseDefinition = { id: "sample database" }; -var collectionDefinition = { id: "sample collection" }; -var documentDefinition = { id: "hello world doc", content: "Hello World!" }; - -client.createDatabase(databaseDefinition, function(err, database) { - if(err) return console.log(err); - console.log('created db'); - - client.createCollection(database._self, collectionDefinition, function(err, collection) { - if(err) return console.log(err); - - console.log('created collection'); - - client.createDocument(collection._self, documentDefinition, function(err, document) { - if(err) return console.log(err); - - console.log('Created Document with content: ', document.content); - cleanup(client, database); - }); - }); -}); - -function cleanup(client, database) { - client.deleteDatabase(database._self, function(err) { - if(err) console.log(err); - }) -} -- -##Community -- [DoQmentDB](https://github.com/a8m/doqmentdb) - A Promise-based DocumentDB client for MongoDB users diff --git a/source/test/consistentHashRingTests.js b/source/test/consistentHashRingTests.js index a66f6a8..c992360 100644 --- a/source/test/consistentHashRingTests.js +++ b/source/test/consistentHashRingTests.js @@ -24,7 +24,7 @@ SOFTWARE. "use strict"; var assert = require("assert"); -var ConsistentHashRing = require("../lib/Hash/consistentHashRing").ConsistentHashRing; +var ConsistentHashRing = require("../lib/hash/consistentHashRing").ConsistentHashRing; describe("ConsistentHashRing new()", function () { it("valid arguments does not throw", function () { diff --git a/source/test/documentClientTests.js b/source/test/documentClientTests.js new file mode 100644 index 0000000..1a82545 --- /dev/null +++ b/source/test/documentClientTests.js @@ -0,0 +1,238 @@ +/* +The MIT License (MIT) +Copyright (c) 2014 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +"use strict"; + +var lib = require("../lib/"), + testConfig = require("./_testConfig"), + assert = require("assert"); + +var DocumentClient = lib.DocumentClient, + Constants = lib.Constants; + +describe("DocumentClient Tests", function () { + var host = testConfig.host; + var masterKey = testConfig.masterKey; + var client = new DocumentClient(host, { masterKey: masterKey }); + + describe("setIsUpsertHeader", function () { + it("Should add is-upsert header.", function (done) { + var headers = client.defaultHeaders; + assert.equal(undefined, headers[Constants.HttpHeaders.IsUpsert]); + client.setIsUpsertHeader(headers); + assert.equal(true, headers[Constants.HttpHeaders.IsUpsert]); + done(); + }); + + it("Should update is-upsert header.", function (done) { + var headers = {}; + headers[Constants.HttpHeaders.IsUpsert] = false; + assert.equal(false, headers[Constants.HttpHeaders.IsUpsert]); + client.setIsUpsertHeader(headers); + assert.equal(true, headers[Constants.HttpHeaders.IsUpsert]); + done(); + }); + + it("Should throw on undefined headers", function (done) { + assert.throws( + function () { client.setIsUpsertHeader(); }, + /The "headers" parameter must not be null or undefined/ + ); + done(); + }); + + it("Should throw on null headers", function (done) { + assert.throws( + function () { client.setIsUpsertHeader(null); }, + /The "headers" parameter must not be null or undefined/ + ); + done(); + }); + + it("Should throw on invalid string headers", function (done) { + assert.throws( + function () { client.setIsUpsertHeader(""); }, + /The "headers" parameter must be an instance of "Object". Actual type is: "string"./ + ); + done(); + }); + + it("Should throw on invalid number headers", function (done) { + assert.throws( + function () { client.setIsUpsertHeader(0); }, + /The "headers" parameter must be an instance of "Object". Actual type is: "number"./ + ); + done(); + }); + + it("Should throw on invalid boolean headers", function (done) { + assert.throws( + function () { client.setIsUpsertHeader(false); }, + /The "headers" parameter must be an instance of "Object". Actual type is: "boolean"./ + ); + done(); + }); + }); + + describe("sprintf", function () { + it("0 strings", function (done) { + assert.equal("foo", client.sprintf("foo")); + done(); + }); + + it("1 string", function (done) { + assert.equal("foo", client.sprintf("%s", "foo")); + done(); + }); + + it("2 strings", function (done) { + assert.equal("foobar", client.sprintf("%s%s", "foo", "bar")); + done(); + }); + + it("3 strings", function (done) { + assert.equal("foobarbaz", client.sprintf("%s%s%s", "foo", "bar", "baz")); + done(); + }); + + it("%% escapes", function (done) { + assert.equal('%s', client.sprintf("%%s", 'foo')); + done(); + }); + }); + + describe("validateOptionsAndCallback Unit Tests", function () { + it("no parameters", function (done) { + var result = client.validateOptionsAndCallback(); + + assert.notEqual(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal(undefined, result.callback); + done(); + }); + + it("options", function (done) { + var result = client.validateOptionsAndCallback({}); + + assert.notEqual(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal(undefined, result.callback); + done(); + }); + + it("callback", function (done) { + var result = client.validateOptionsAndCallback(function () { }); + assert.notEqual(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal("function", typeof result.callback); + done(); + }); + + it("options, callback.", function (done) { + var result = client.validateOptionsAndCallback({}, function () { }); + assert.notEqual(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal("function", typeof result.callback); + done(); + }); + + it("undefined, callback", function (done) { + var result = client.validateOptionsAndCallback(undefined, function () { }); + assert.notEqual(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal("function", typeof result.callback); + done(); + }); + + it("null, callback", function (done) { + var result = client.validateOptionsAndCallback(null, function () { }); + assert.equal(null, result.options); + assert.equal("object", typeof result.options); + + assert.equal("function", typeof result.callback); + done(); + }); + + + it("invalid string options", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback("foo", function () { }); }, + /The "options" parameter must be of type "object". Actual type is: "string"/ + ); + done(); + }); + + it("invalid number options", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback(0, function () { }); }, + /The "options" parameter must be of type "object". Actual type is: "number"/ + ); + done(); + }); + + it("invalid bool options", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback(false, function () { }); }, + /The "options" parameter must be of type "object". Actual type is: "boolean"/ + ); + done(); + }); + + it("invalid string callback", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback({}, "bar"); }, + /The "callback" parameter must be of type "function". Actual type is: "string"/ + ); + done(); + }); + + it("invalid number callback", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback({}, 0); }, + /The "callback" parameter must be of type "function". Actual type is: "number"/ + ); + done(); + }); + + it("invalid boolean callback", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback({}, false); }, + /The "callback" parameter must be of type "function". Actual type is: "boolean"/ + ); + done(); + }); + + it("invalid options, invalid callback", function (done) { + assert.throws( + function () { client.validateOptionsAndCallback("foo", "bar"); }, + /The "options" parameter must be of type "object". Actual type is: "string"/ + ); + done(); + }); + }); +}); \ No newline at end of file diff --git a/source/test/hashPartitionResolverTests.js b/source/test/hashPartitionResolverTests.js index 6e819d8..05429bb 100644 --- a/source/test/hashPartitionResolverTests.js +++ b/source/test/hashPartitionResolverTests.js @@ -24,7 +24,7 @@ SOFTWARE. "use strict"; var assert = require("assert"); -var HashPartitionResolver = require("../lib/Hash/hashPartitionResolver").HashPartitionResolver; +var HashPartitionResolver = require("../lib/hash/hashPartitionResolver").HashPartitionResolver; describe("HashPartitionResolver new()", function () { it(" does not throw", function () { diff --git a/source/test/murmurHashTests.js b/source/test/murmurHashTests.js index de540d3..0b2674b 100644 --- a/source/test/murmurHashTests.js +++ b/source/test/murmurHashTests.js @@ -23,7 +23,7 @@ SOFTWARE. "use strict"; -var MurmurHash = require("../lib/Hash/murmurHash").MurmurHash; +var MurmurHash = require("../lib/hash/murmurHash").MurmurHash; var assert = require("assert") describe("MurmurHash.hash", function () { diff --git a/source/test/rangePartitionResolverTests.js b/source/test/rangePartitionResolverTests.js new file mode 100644 index 0000000..5aa2ab1 --- /dev/null +++ b/source/test/rangePartitionResolverTests.js @@ -0,0 +1,431 @@ +/* +The MIT License (MIT) +Copyright (c) 2014 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +"use strict"; + +var lib = require("../lib/"), + assert = require("assert"); + +var Range = lib.Range, + RangePartitionResolver = lib.RangePartitionResolver; + +describe("RangePartitionResolver", function () { + describe("constructor", function () { + it("missing partitionKeyExtractor throws", function (done) { + var expetcedError = /Error: partitionKeyExtractor cannot be null or undefined/; + + assert.throws( + function () { + var r = new RangePartitionResolver(); + }, + expetcedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver(undefined); + }, + expetcedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver(null); + }, + expetcedError + ); + + done(); + }); + + it("invalid partitionKeyExtractor throws", function (done) { + var expetcedError = /partitionKeyExtractor must be either a 'string' or a 'function'/; + + assert.throws( + function () { + var r = new RangePartitionResolver(0); + }, + expetcedError + ); + + assert.throws( + function () { + var r = RangePartitionResolver(true); + }, + expetcedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver(NaN); + }, + expetcedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver([]); + }, + expetcedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver({}); + }, + expetcedError + ); + + + done(); + }); + + it("missing partitionKeyMap throws", function (done) { + var expectedError = /Error: partitionKeyMap cannot be null or undefined/; + + assert.throws( + function () { + var r = new RangePartitionResolver(""); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver(function () { + }); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver("", null); + }, + expectedError + ); + + done(); + }); + + it("invalid partitionKeyMap throws", function (done) { + var expectedError = /Error: partitionKeyMap has to be an Array/; + + assert.throws( + function () { + var r = new RangePartitionResolver("", 0); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver("", ""); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver("", true); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver("", NaN); + }, + expectedError + ); + + assert.throws( + function () { + var r = new RangePartitionResolver("", {}); + }, + expectedError + ); + + var r = new RangePartitionResolver("", new Array()); + done(); + }); + + it("valid RangePartitionResolver", function (done) { + var resolver = new RangePartitionResolver("", []); + assert(resolver); + assert.strictEqual(resolver.partitionKeyExtractor, ""); + assert.deepEqual(resolver.partitionKeyMap, []); + done(); + }); + }); + + describe("_getFirstContainingMapEntryOrNull", function () { + it("_getFirstContainingMapEntryOrNull - empty map returns null", function (done) { + var ranges = [undefined, null, 0, "", true, [], {}, NaN, new Range()]; + var resolver = new RangePartitionResolver("", []); + ranges.forEach(function (r) { + var result = resolver._getFirstContainingMapEntryOrNull(r); + assert.equal(result, null); + }); + done(); + }); + + it("_tryGetContainingRange - map with no containing entry returns null", function (done) { + var mapEntry = { range: new Range({ low: "A" }), link: "link1" }; + var resolver = new RangePartitionResolver("key", [mapEntry]); + var result = resolver._getFirstContainingMapEntryOrNull(new Range({ low: "B" })); + assert.equal(result, null); + done(); + }); + + it("_tryGetContainingRange - map with single containing entry returns entry", function (done) { + var mapEntry = { range: new Range(), link: "link1" }; + var resolver = new RangePartitionResolver("key", [mapEntry]); + var result = resolver._getFirstContainingMapEntryOrNull(new Range()); + assert.deepEqual(result, { range: new Range(), link: "link1" }); + done(); + }); + + it("_tryGetContainingRange - map with more multiple containing entries returns first entry", function (done) { + var map1 = [ + { range: new Range({ low: "A", high: "B" }), link: "link1" }, + { range: new Range({ low: "A" }), link: "link2" } + ]; + + var resolver1 = new RangePartitionResolver("key", map1); + var result1 = resolver1._getFirstContainingMapEntryOrNull(new Range({ low: "A" })); + assert.strictEqual(result1.link, "link1"); + + var map2 = [ + { range: new Range({ low: "A" }), link: "link2" }, + { range: new Range({ low: "A", high: "Z" }), link: "link1" } + ]; + + var resolver2 = new RangePartitionResolver("key", map2); + var result2 = resolver2._getFirstContainingMapEntryOrNull(new Range({ low: "A" })); + assert.strictEqual(result2.link, "link2"); + done(); + }); + }); + + describe("resolveForCreate", function () { + it("_tryGetContainingRange - map containing parition key returns corresponding link", function (done) { + var resolver = new RangePartitionResolver("key", [ + { range: new Range({ low: "A", high: "M" }), link: "link1" }, + { range: new Range({ low: "N", high: "Z" }), link: "link2" } + ]); + var result = resolver.resolveForCreate("X"); + assert.strictEqual(result, "link2"); + done(); + }); + + it("_tryGetContainingRange - map not containing parition key throws", function (done) { + var resolver = new RangePartitionResolver("key", [ + { range: new Range({ low: "A", high: "M" }), link: "link1" } + ]); + + assert.throws( + function () { + var result = resolver.resolveForCreate("X"); + }, + /Error: Invalid operation: A containing range for 'X,X' doesn't exist in the partition map./ + ); + done(); + }); + }); + + var resolveForReadTest = function (resolver, partitionKey, expectedLinks) { + var result = resolver.resolveForRead(partitionKey); + assert.deepEqual(expectedLinks, result); + }; + + describe("resolveForRead", function () { + var resolver = new RangePartitionResolver( + function (doc) { + return doc.key; + }, + [ + { + range: new Range({ low: "A", high: "M" }), + link: "link1" + }, + { + range: new Range({ low: "N", high: "Z" }), + link: "link2" + } + ]); + + it("undefined", function (done) { + var partitionKey = undefined; + var expectedLinks = ["link1", "link2"]; + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + + it("null", function (done) { + var partitionKey = null; + var expectedLinks = ["link1", "link2"]; + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + }); + + describe("resolveForRead string", function () { + var resolver = new RangePartitionResolver( + function (doc) { + return doc.key; + }, + [ + { + range: new Range({ low: "A", high: "M" }), + link: "link1" + }, + { + range: new Range({ low: "N", high: "Z" }), + link: "link2" + } + ]); + + it("point", function (done) { + var partitionKey = new Range({ low: "D" }); + var expectedLinks = ["link1"]; + resolveForReadTest(resolver, partitionKey, expectedLinks); + + var partitionKey2 = new Range({ low: "Q" }); + var expectedLinks2 = ["link2"]; + resolveForReadTest(resolver, partitionKey2, expectedLinks2); + done(); + }); + + it("range", function (done) { + var partitionKey = new Range({ low: "D", high: "Q" }); + var expectedLinks = ["link1", "link2"]; + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + + it("array of ranges", function (done) { + var partitionKey = [ + new Range({ low: "A", high: "B" }), + new Range({ low: "Q" }) + ]; + var expectedLinks = ["link1", "link2"]; + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + }); + + describe("resolveForRead number", function () { + var partitionKeyExtractor = function (doc) { + return doc.key; + }; + + var partitionKeyMap = [ + { + range: new Range({ low: 1, high: 15 }), + link: "link1" + }, + { + range: new Range({ low: 16, high: 30 }), + link: "link2" + } + ]; + + it("point, default compareFunction", function (done) { + var resolver = new RangePartitionResolver(partitionKeyExtractor, partitionKeyMap); + + var partitionKey = new Range({ low: 2 }); + var expectedLinks = ["link2"]; + + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + + it("point, custom compareFunction", function (done) { + var resolver = new RangePartitionResolver(partitionKeyExtractor, partitionKeyMap, function (a, b) { + return a - b; + }); + + var partitionKey = new Range({ low: 2 }); + var expectedLinks = ["link1"]; + + resolveForReadTest(resolver, partitionKey, expectedLinks); + done(); + }); + }); + + describe("compareFunction", function () { + var invalidCompareFunctionTest = function (compareFunction, done) { + assert.throws( + function () { + var resolver = new RangePartitionResolver( + "key", + [{ range: new Range({ low: "A" }), link: "link1" }], + compareFunction + ); + }, + /Invalid argument: 'compareFunction' is not a function/); + done(); + } + + it("invalid compareFunction - null", function (done) { + var compareFunction = null; + invalidCompareFunctionTest(compareFunction, done); + }); + + it("invalid compareFunction - string", function (done) { + var compareFunction = ""; + invalidCompareFunctionTest(compareFunction, done); + }); + + it("invalid compareFunction - number", function (done) { + var compareFunction = 0; + invalidCompareFunctionTest(compareFunction, done); + }); + + it("invalid compareFunction - boolean", function (done) { + var compareFunction = false; + invalidCompareFunctionTest(compareFunction, done); + }); + + it("invalid compareFunction - object", function (done) { + var compareFunction = {}; + invalidCompareFunctionTest(compareFunction, done); + }); + + it("compareFunction throws", function (done) { + var resolver = new RangePartitionResolver( + "key", + [{ range: new Range({ low: "A" }), link: "link1" }], + function (a, b) { throw new Error("Compare error"); } + ); + + assert.throws( + function () { + var result = resolver.resolveForRead("A", ["link1"]); + }, + /Error: Compare error/); + done(); + }); + }); +}); diff --git a/source/test/rangeTests.js b/source/test/rangeTests.js new file mode 100644 index 0000000..9cddabe --- /dev/null +++ b/source/test/rangeTests.js @@ -0,0 +1,502 @@ +/* +The MIT License (MIT) +Copyright (c) 2014 Microsoft Corporation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +"use strict"; + +var lib = require("../lib/"), + assert = require("assert"); + +var Range = lib.Range; + +describe("Range Tests", function () { + describe("constructor", function () { + var invalidOptionsTest = function (options, expectedError, done) { + assert.throws( + function () { + var r = new Range(options); + }, + expectedError); + done(); + } + + var optionsIsNullTest = function (options, done) { + invalidOptionsTest(options, /Invalid argument: 'options' is null/, done); + } + + var optionsIsNotAnObjectTest = function (options, done) { + invalidOptionsTest(options, /Invalid argument: 'options' is not an object/, done); + } + + var invalidRangeTest = function (options, done) { + invalidOptionsTest(options, /Invalid argument: 'options.low' must be less than or equal than 'options.high'/, done); + } + + it("options - undefined (ommited argument)", function (done) { + assert(new Range()); + done(); + }); + + it("options - undefined (literal argument)", function (done) { + assert(new Range(undefined)); + done(); + }); + + it("options - null ", function (done) { + var options = null; + optionsIsNullTest(options, done); + }); + + it("options - number", function (done) { + var options = 0; + optionsIsNotAnObjectTest(options, done); + }); + + it("invalid options - string", function (done) { + var options = ""; + optionsIsNotAnObjectTest(options, done); + }); + + it("invalid options - boolean", function (done) { + var options = false; + optionsIsNotAnObjectTest(options, done); + }); + + it("Range instances are frozen", function (done) { + var r = new Range(); + + assert.throws( + function () { + r.compareFunction = 1; + }, + /Can't add property compareFunction, object is not extensible/ + ); + + done(); + }); + }); + + describe("_contains", function () { + it("undefined,undefined contains undefined is true", function (done) { + var r = new Range(); + assert(r._contains(undefined)); + done(); + }); + + it("undefined,undefined contains null is false", function (done) { + var r = new Range(); + assert(!r._contains(null)); + done(); + }); + + it("null,null contains undefined is true", function (done) { + var r = new Range({ low: null }); + assert(r._contains(null)); + done(); + }); + + it("null,null contains null is true", function (done) { + var r = new Range({ low: null }); + assert(r._contains(null)); + done(); + }); + + it("range contains self is true - default range", function (done) { + var r = new Range(); + assert(r._contains(r)); + done(); + }); + + it("range contains self is true - non-default range", function (done) { + var r = new Range({ low: "A" }); + assert(r._contains(r)); + done(); + }); + + it("A,D contains B,C is true", function (done) { + var r1 = new Range({ low: "A", high: "D" }); + var r2 = new Range({ low: "B", high: "C" }); + assert(r1._contains(r2)); + done(); + }); + + it("B,C contains A,D is false", function (done) { + var r1 = new Range({ low: "B", high: "C" }); + var r2 = new Range({ low: "A", high: "D" }); + assert(!r1._contains(r2)); + done(); + }); + + it("A,C contains B,D is false", function (done) { + var r1 = new Range({ low: "A", high: "C" }); + var r2 = new Range({ low: "B", high: "D" }); + assert(!r1._contains(r2)); + done(); + }); + + it("B,D contains A,C is false", function (done) { + var r1 = new Range({ low: "B", high: "D" }); + var r2 = new Range({ low: "A", high: "C" }); + assert(!r1._contains(r2)); + done(); + }); + + it("A,B contains B,C is false", function (done) { + var r1 = new Range({ low: "A", high: "B" }); + var r2 = new Range({ low: "B", high: "C" }); + assert(!r1._contains(r2)); + done(); + }); + + it("B,C contains A,B is false", function (done) { + var r1 = new Range({ low: "B", high: "C" }); + var r2 = new Range({ low: "A", high: "B" }); + assert(!r1._contains(r2)); + done(); + }); + + it("A,B contains C,D is false", function (done) { + var r1 = new Range({ low: "A", high: "B" }); + var r2 = new Range({ low: "C", high: "D" }); + assert(!r1._contains(r2)); + done(); + }); + + it("C,D contains A,B is false", function (done) { + var r1 = new Range({ low: "C", high: "D" }); + var r2 = new Range({ low: "A", high: "B" }); + assert(!r1._contains(r2)); + done(); + }); + + it("A,C contains B is true", function (done) { + var r1 = new Range({ low: "A", high: "C" }); + assert(r1._contains("B")); + done(); + }); + + it("B,C contains A is false", function (done) { + var r1 = new Range({ low: "B", high: "C" }); + assert(!r1._contains("A")); + done(); + }); + + it("A,B contains C is false", function (done) { + var r1 = new Range({ low: "A", high: "B" }); + assert(!r1._contains("C")); + done(); + }); + }); + + describe("_containsPoint", function () { + var range = new Range({ low: 1, high: 3 }); + + it("numbers, default comparison", function (done) { + assert(range._containsPoint(20)); + done(); + }); + + it("numbers, custom comparison", function (done) { + + assert(!range._containsPoint(20, function (a, b) { + return a - b; + })); + + done(); + }); + }); + + describe("_containsRange", function () { + var range = new Range({ low: 1, high: 3 }); + + it("numbers, default comparison", function (done) { + assert(range._containsRange({ low: 20, high: 29})); + done(); + }); + + it("numbers, custom comparison", function (done) { + assert(!range._containsRange({ low: 20, high: 29 }, function (a, b) { + return a - b; + })); + + done(); + }); + }); + + describe("_intersect", function () { + var otherIsUndefinedOrNullTest = function (other, done) { + var r = new Range(); + assert.throws( + function () { + r._intersect(other); + }, + /Invalid Argument: 'other' is undefined or null/ + ); + done(); + }; + + it("error - other is undefined", function (done) { + otherIsUndefinedOrNullTest(undefined, done); + }); + + it("error - other is null", function (done) { + otherIsUndefinedOrNullTest(null, done); + }); + + it("range intersect self is true - default range", function (done) { + var r = new Range(); + assert(r._intersect(r)); + done(); + }); + + it("R intersect R is true - non default range", function (done) { + var r = new Range({ low: 1, high: "2" }); + assert(r._intersect(r)); + done(); + }); + + it("A,D insersects B,C is true", function (done) { + var r1 = new Range({ low: "A", high: "D" }); + var r2 = new Range({ low: "B", high: "C" }); + assert(r1._intersect(r2)); + done(); + }); + + it("B,C insersects A,D is true", function (done) { + var r1 = new Range({ low: "B", high: "C" }); + var r2 = new Range({ low: "A", high: "D" }); + assert(r1._intersect(r2)); + done(); + }); + + it("A,C insersects B,D is true", function (done) { + var r1 = new Range({ low: "A", high: "C" }); + var r2 = new Range({ low: "B", high: "D" }); + assert(r1._intersect(r2)); + assert(r2._intersect(r1)); + done(); + }); + + it("B,D insersects A,C is true", function (done) { + var r1 = new Range({ low: "B", high: "D" }); + var r2 = new Range({ low: "A", high: "C" }); + assert(r1._intersect(r2)); + done(); + }); + + it("A,B insersects B,C is true", function (done) { + var r1 = new Range({ low: "A", high: "B" }); + var r2 = new Range({ low: "B", high: "C" }); + assert(r1._intersect(r2)); + assert(r2._intersect(r1)); + done(); + }); + + it("B,C insersects A,B is true", function (done) { + var r1 = new Range({ low: "B", high: "C" }); + var r2 = new Range({ low: "A", high: "B" }); + assert(r1._intersect(r2)); + done(); + }); + + it("A,B insersects C,D is false", function (done) { + var r1 = new Range({ low: "A", high: "B" }); + var r2 = new Range({ low: "C", high: "D" }); + assert(!r1._intersect(r2)); + done(); + }); + + it("C,D insersects A,B is false", function (done) { + var r1 = new Range({ low: "C", high: "D" }); + var r2 = new Range({ low: "A", high: "B" }); + assert(!r1._intersect(r2)); + done(); + }); + }); + + describe("_toString", function () { + var toStringTest = function (options, expectedString, done) { + var r = new Range(options); + assert.strictEqual(r._toString(), expectedString); + done(); + }; + + it("undefined values", function (done) { + toStringTest(undefined, "undefined,undefined", done); + }); + it("null values", function (done) { + toStringTest({ low: null }, "null,null", done); + }); + it("NaN values", function (done) { + toStringTest({ low: NaN }, "NaN,NaN", done); + }); + it("number values", function (done) { + toStringTest({ low: 1 }, "1,1", done); + }); + it("string values", function (done) { + toStringTest({ low: "a" }, "a,a", done); + }); + it("boolean values", function (done) { + toStringTest({ low: false, high: true }, "false,true", done); + }); + it("object values", function (done) { + toStringTest({ low: {} }, "[object Object],[object Object]", done); + }); + }); + + describe("_compare", function () { + var r = new Range(); + + var compareAsNumbers = function (a, b) { + return a - b; + } + + var constantCompareFunction = function (a, b) { + return 0; + }; + + it("(undefined, undefined) === 0", function (done) { + assert(r._compare() === 0); + assert(r._compare(undefined) === 0); + assert(r._compare(undefined, undefined) === 0); + done(); + }); + + it("(undefined, y) > 0", function (done) { + assert(r._compare(undefined, null) > 0); + assert(r._compare(undefined, -NaN) > 0); + assert(r._compare(undefined, 0) > 0); + assert(r._compare(undefined, NaN) > 0); + assert(r._compare(undefined, true) > 0); + assert(r._compare(undefined, false) > 0); + assert(r._compare(undefined, "a") > 0); + assert(r._compare(undefined, "undefined") > 0); + assert(r._compare(undefined, "z") > 0); + assert(r._compare(undefined, []) > 0); + assert(r._compare(undefined, {}) > 0); + assert(r._compare(undefined, 2, constantCompareFunction) > 0); + assert(r._compare(undefined, 2, compareAsNumbers) > 0); + + done(); + }); + + it("(x, undefined) < 0", function (done) { + assert(r._compare(null) < 0); + assert(r._compare(-NaN) < 0); + assert(r._compare(0) < 0); + assert(r._compare(NaN) < 0); + assert(r._compare(true) < 0); + assert(r._compare(false) < 0); + assert(r._compare("a") < 0); + assert(r._compare("undefined") < 0); + assert(r._compare("z") < 0); + assert(r._compare([]) < 0); + assert(r._compare({}) < 0); + assert(r._compare(1, undefined, constantCompareFunction) < 0); + assert(r._compare(1, undefined, compareAsNumbers) < 0); + done(); + }); + + it("values as strings (default)", function (done) { + assert(r._compare("A", "B") < 0); + assert(r._compare("", "") === 0); + assert(r._compare("B", "A") > 0); + assert(r._compare("10", "2") < 0); + assert(r._compare(10, "02") > 0); + assert(r._compare(10, 2) < 0); + assert(r._compare(null, "nulm") < 0); + assert(r._compare(null, "null") === 0); + assert(r._compare(null, "nulk") > 0); + assert(r._compare(true, "truf") < 0); + assert(r._compare(true, "true") === 0); + assert(r._compare(true, "trud") > 0); + assert(r._compare({}, "[object Object]") === 0); + done(); + }); + + it("values as numbers", function (done) { + + assert(r._compare(undefined, 2, compareAsNumbers) > 0); + assert(r._compare(1, 2, compareAsNumbers) < 0); + assert(r._compare(0, 0, compareAsNumbers) === 0); + assert(r._compare(10, 2, compareAsNumbers) > 0); + done(); + }); + + it("always return 0", function (done) { + assert(r._compare(1, 2, constantCompareFunction) === 0); + assert(r._compare(2, 1, constantCompareFunction) === 0); + done(); + }); + }); + + describe("_isRange", function () { + it("_isRange(undefined) is false", function (done) { + assert(!Range._isRange()); + done(); + }); + + it("_isRange(null) is false", function (done) { + assert(!Range._isRange(null)); + done(); + }); + + it("_isRange(non-object) is false", function (done) { + var points = [ + undefined, + null, + 1, + "", + true, + NaN, + function () { + }, + {}, + { + low: "" + } + ]; + + for (var i = 0; i < points.length; i++) { + assert(!Range._isRange(points[i])); + } + + done(); + }); + + it("_isRange(point) is false", function (done) { + var ranges = [ + { + low: "", + high: 1 + }, + new Range() + ]; + + for (var i = 0; i < ranges.length; i++) { + assert(Range._isRange(ranges[i])); + } + + done(); + }); + }); +}); diff --git a/source/test/readme.md b/source/test/readme.md index 7285fcf..e1a2b28 100644 --- a/source/test/readme.md +++ b/source/test/readme.md @@ -1,6 +1,6 @@ Follow these instructions to run the tests locally. -##Prerequisites +## Prerequisites 1. Clone Azure/azure-documentdb-node repository Please clone the source and tests from [https://github.com/Azure/azure-documentdb-node](https://github.com/Azure/azure-documentdb-node) @@ -11,7 +11,7 @@ Please clone the source and tests from [https://github.com/Azure/azure-documentd 3. Install mocha package globally > npm install -g mocha -##Running the tests +## Running the tests Using your command-line tool, from the root of your local copy of azure-documentdb-node repository: If you are contributing changes and submitting PR then you need to ensure that you run the tests against your local copy of the source, and not the published npm package. diff --git a/source/test/test.js b/source/test/test.js index 0644a2e..dfd7949 100644 --- a/source/test/test.js +++ b/source/test/test.js @@ -23,16 +23,18 @@ SOFTWARE. "use strict"; -var Base = require("documentdb").Base - , DocumentDBClient = require("documentdb").DocumentClient - , DocumentBase = require("documentdb").DocumentBase - , Constants = require("documentdb").Constants - , assert = require("assert") - , testConfig = require("./_testConfig") - , Stream = require("stream") - , Range = require("documentdb").Range - , RangePartitionResolver = require("documentdb").RangePartitionResolver - , HashPartitionResolver = require("documentdb").HashPartitionResolver; +var lib = require("../lib/"), + assert = require("assert"), + testConfig = require("./_testConfig"), + Stream = require("stream"); + +var Base = lib.Base, + DocumentDBClient = lib.DocumentClient, + DocumentBase = lib.DocumentBase, + Constants = lib.Constants, + Range = lib.Range, + RangePartitionResolver = lib.RangePartitionResolver, + HashPartitionResolver = lib.HashPartitionResolver; process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; @@ -2285,951 +2287,7 @@ describe("NodeJS CRUD Tests", function() { }); }); - describe("setIsUpsertHeader Unit Tests", function () { - var client = new DocumentDBClient(host, { masterKey: masterKey }); - - it("[nativeApi] Should add is-upsert header.", function (done) { - var headers = client.defaultHeaders; - assert.equal(undefined, headers[Constants.HttpHeaders.IsUpsert]); - client.setIsUpsertHeader(headers); - assert.equal(true, headers[Constants.HttpHeaders.IsUpsert]); - done(); - }); - - it("[nativeApi] Should update is-upsert header.", function (done) { - var headers = {}; - headers[Constants.HttpHeaders.IsUpsert] = false; - assert.equal(false, headers[Constants.HttpHeaders.IsUpsert]); - client.setIsUpsertHeader(headers); - assert.equal(true, headers[Constants.HttpHeaders.IsUpsert]); - done(); - }); - - it("[nativeApi] Should throw on undefined headers", function (done) { - assert.throws( - function () { client.setIsUpsertHeader(); }, - /The "headers" parameter must not be null or undefined/ - ); - done(); - }); - - it("[nativeApi] Should throw on null headers", function (done) { - assert.throws( - function () { client.setIsUpsertHeader(null); }, - /The "headers" parameter must not be null or undefined/ - ); - done(); - }); - - it("[nativeApi] Should throw on invalid string headers", function (done) { - assert.throws( - function () { client.setIsUpsertHeader(""); }, - /The "headers" parameter must be an instance of "Object". Actual type is: "string"./ - ); - done(); - }); - - it("[nativeApi] Should throw on invalid number headers", function (done) { - assert.throws( - function () { client.setIsUpsertHeader(0); }, - /The "headers" parameter must be an instance of "Object". Actual type is: "number"./ - ); - done(); - }); - - it("[nativeApi] Should throw on invalid boolean headers", function (done) { - assert.throws( - function () { client.setIsUpsertHeader(false); }, - /The "headers" parameter must be an instance of "Object". Actual type is: "boolean"./ - ); - done(); - }); - - }); - - describe("validateOptionsAndCallback Unit Tests", function () { - var client = new DocumentDBClient(host, { masterKey: masterKey }); - - it("[nativeApi] no parameters", function (done) { - var result = client.validateOptionsAndCallback(); - - assert.notEqual(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal(undefined, result.callback); - done(); - }); - - it("[nativeApi] options", function (done) { - var result = client.validateOptionsAndCallback({}); - - assert.notEqual(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal(undefined, result.callback); - done(); - }); - - it("[nativeApi] callback", function (done) { - var result = client.validateOptionsAndCallback(function(){}); - assert.notEqual(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal("function", typeof result.callback); - done(); - }); - - it("[nativeApi] options, callback.", function (done) { - var result = client.validateOptionsAndCallback({}, function(){}); - assert.notEqual(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal("function", typeof result.callback); - done(); - }); - - it("[nativeApi] undefined, callback", function (done) { - var result = client.validateOptionsAndCallback(undefined, function(){}); - assert.notEqual(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal("function", typeof result.callback); - done(); - }); - - it("[nativeApi] null, callback", function (done) { - var result = client.validateOptionsAndCallback(null, function () { }); - assert.equal(null, result.options); - assert.equal("object", typeof result.options); - - assert.equal("function", typeof result.callback); - done(); - }); - - - it("[nativeApi] invalid string options", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback("foo", function () { }); }, - /The "options" parameter must be of type "object". Actual type is: "string"/ - ); - done(); - }); - - it("[nativeApi] invalid number options", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback(0, function () { }); }, - /The "options" parameter must be of type "object". Actual type is: "number"/ - ); - done(); - }); - - it("[nativeApi] invalid bool options", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback(false, function () { }); }, - /The "options" parameter must be of type "object". Actual type is: "boolean"/ - ); - done(); - }); - - it("[nativeApi] invalid string callback", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback({}, "bar"); }, - /The "callback" parameter must be of type "function". Actual type is: "string"/ - ); - done(); - }); - - it("[nativeApi] invalid number callback", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback({}, 0); }, - /The "callback" parameter must be of type "function". Actual type is: "number"/ - ); - done(); - }); - - it("[nativeApi] invalid boolean callback", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback({}, false); }, - /The "callback" parameter must be of type "function". Actual type is: "boolean"/ - ); - done(); - }); - - it("[nativeApi] invalid options, invalid callback", function (done) { - assert.throws( - function () { client.validateOptionsAndCallback("foo", "bar"); }, - /The "options" parameter must be of type "object". Actual type is: "string"/ - ); - done(); - }); - }); - - describe("sprintf Unit Tests", function () { - var client = new DocumentDBClient(host, { masterKey: masterKey }); - - it("[nativeApi] 0 strings", function (done) { - assert.equal("foo", client.sprintf("foo")); - done(); - }); - - it("[nativeApi] 1 string", function (done) { - assert.equal("foo", client.sprintf("%s", "foo")); - done(); - }); - - it("[nativeApi] 2 strings", function (done) { - assert.equal("foobar", client.sprintf("%s%s", "foo", "bar")); - done(); - }); - - it("[nativeApi] 3 strings", function (done) { - assert.equal("foobarbaz", client.sprintf("%s%s%s", "foo", "bar", "baz")); - done(); - }); - - it("[nativeApi] %% escapes", function (done) { - assert.equal('%s', client.sprintf("%%s", 'foo')); - done(); - }); - }); - - describe("Range Tests", function () { - describe("constructor", function () { - var invalidOptionsTest = function (options, expectedError, done) { - assert.throws( - function () { - var r = new Range(options); - }, - expectedError); - done(); - } - - var optionsIsNullTest = function (options, done) { - invalidOptionsTest(options, /Invalid argument: 'options' is null/, done); - } - - var optionsIsNotAnObjectTest = function (options, done) { - invalidOptionsTest(options, /Invalid argument: 'options' is not an object/, done); - } - - var comparisonFunctionIsNotAFunctionTest = function (options, done) { - invalidOptionsTest(options, /Invalid argument: 'options.compareFunction' is not a function/, done); - } - - var invalidRangeTest = function (options, done) { - invalidOptionsTest(options, /Invalid argument: 'options.low' must be less than or equal than 'options.high'/, done); - } - - it("[nativeApi] options - undefined (ommited argument)", function (done) { - assert(new Range()); - done(); - }); - - it("[nativeApi] options - undefined (literal argument)", function (done) { - assert(new Range(undefined)); - done(); - }); - - it("[nativeApi] options - null ", function (done) { - var options = null; - optionsIsNullTest(options, done); - }); - - it("[nativeApi] options - number", function (done) { - var options = 0; - optionsIsNotAnObjectTest(options, done); - }); - - it("[nativeApi] invalid options - string", function (done) { - var options = ""; - optionsIsNotAnObjectTest(options, done); - }); - - it("[nativeApi] invalid options - boolean", function (done) { - var options = false; - optionsIsNotAnObjectTest(options, done); - }); - - it("[nativeApi] invalid compareFunction - null", function (done) { - var options = { compareFunction: null }; - comparisonFunctionIsNotAFunctionTest(options, done); - }); - - it("[nativeApi] invalid compareFunction - string", function (done) { - var options = { compareFunction: "" }; - comparisonFunctionIsNotAFunctionTest(options, done); - }); - - it("[nativeApi] invalid compareFunction - number", function (done) { - var options = { compareFunction: 0 }; - comparisonFunctionIsNotAFunctionTest(options, done); - }); - - it("[nativeApi] invalid compareFunction - boolean", function (done) { - var options = { compareFunction: false }; - comparisonFunctionIsNotAFunctionTest(options, done); - }); - - it("[nativeApi] invalid compareFunction - object", function (done) { - var options = { compareFunction: {} }; - comparisonFunctionIsNotAFunctionTest(options, done); - }); - - it("[nativeApi] invalid range - low greater than high", function (done) { - var options = { low: 2, high: 1 }; - invalidRangeTest(options, done); - }); - - it("[nativeApi] compareFunction exception is thrown - inside constructor ", function (done) { - var options = { - low: 0, - high: 1, - compareFunction: function (a, b) { - throw new Error("Compare error"); - } - }; - assert.throws( - function () { - var r = new Range(options); - }, - /Error: Compare error/); - done(); - }); - - it("[nativeApi] compareFunction exception is thrown - outside constructor ", function (done) { - var options = { - low: 0, - high: 1, - compareFunction: function (a, b) { - if (a === 1) { - throw new Error("Compare error"); - } - } - }; - var r = new Range(options); - assert.throws( - function () { - r._compare(1, 0); - }, - /Error: Compare error/); - done(); - }); - - it("[nativeApi] Range instances are frozen", function (done) { - var r = new Range(); - - assert.throws( - function () { - r.compareFunction = 1; - }, - /Cannot assign to read only property 'compareFunction' of / - ); - - done(); - }); - - }); - - describe("contains", function () { - it("[nativeApi] undefined,undefined contains undefined is true", function (done) { - var r = new Range(); - assert(r.contains(undefined)); - done(); - }); - - it("[nativeApi] undefined,undefined contains null is false", function (done) { - var r = new Range(); - assert(!r.contains(null)); - done(); - }); - - it("[nativeApi] null,null contains undefined is true", function (done) { - var r = new Range({ low: null }); - assert(r.contains(null)); - done(); - }); - - it("[nativeApi] null,null contains null is true", function (done) { - var r = new Range({ low: null }); - assert(r.contains(null)); - done(); - }); - - it("[nativeApi] range contains self is true - default range", function (done) { - var r = new Range(); - assert(r.contains(r)); - done(); - }); - - it("[nativeApi] range contains self is true - non-default range", function (done) { - var r = new Range({ low: "A" }); - assert(r.contains(r)); - done(); - }); - - it("[nativeApi] A,D contains B,C is true", function (done) { - var r1 = new Range({ low: "A", high: "D" }); - var r2 = new Range({ low: "B", high: "C" }); - assert(r1.contains(r2)); - done(); - }); - - it("[nativeApi] B,C contains A,D is false", function (done) { - var r1 = new Range({ low: "B", high: "C" }); - var r2 = new Range({ low: "A", high: "D" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] A,C contains B,D is false", function (done) { - var r1 = new Range({ low: "A", high: "C" }); - var r2 = new Range({ low: "B", high: "D" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] B,D contains A,C is false", function (done) { - var r1 = new Range({ low: "B", high: "D" }); - var r2 = new Range({ low: "A", high: "C" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] A,B contains B,C is false", function (done) { - var r1 = new Range({ low: "A", high: "B" }); - var r2 = new Range({ low: "B", high: "C" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] B,C contains A,B is false", function (done) { - var r1 = new Range({ low: "B", high: "C" }); - var r2 = new Range({ low: "A", high: "B" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] A,B contains C,D is false", function (done) { - var r1 = new Range({ low: "A", high: "B" }); - var r2 = new Range({ low: "C", high: "D" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] C,D contains A,B is false", function (done) { - var r1 = new Range({ low: "C", high: "D" }); - var r2 = new Range({ low: "A", high: "B" }); - assert(!r1.contains(r2)); - done(); - }); - - it("[nativeApi] A,C contains B is true", function (done) { - var r1 = new Range({ low: "A", high: "C" }); - assert(r1.contains("B")); - done(); - }); - - it("[nativeApi] B,C contains A is false", function (done) { - var r1 = new Range({ low: "B", high: "C" }); - assert(!r1.contains("A")); - done(); - }); - - it("[nativeApi] A,B contains C is false", function (done) { - var r1 = new Range({ low: "A", high: "B" }); - assert(!r1.contains("C")); - done(); - }); - }); - - describe("intersect", function () { - var otherIsUndefinedOrNullTest = function (other, done) { - var r = new Range(); - assert.throws( - function () { - r.intersect(other); - }, - /Invalid Argument: 'other' is undefined or null/ - ); - done(); - }; - - it("[nativeApi] error - other is undefined", function (done) { - otherIsUndefinedOrNullTest(undefined, done); - }); - - it("[nativeApi] error - other is null", function (done) { - otherIsUndefinedOrNullTest(null, done); - }); - - it("[nativeApi] range intersect self is true - default range", function (done) { - var r = new Range(); - assert(r.intersect(r)); - done(); - }); - - it("[nativeApi] R intersect R is true - non default range", function (done) { - var r = new Range({ low: 1, high: "2" }); - assert(r.intersect(r)); - done(); - }); - - it("[nativeApi] A,D insersects B,C is true", function (done) { - var r1 = new Range({ low: "A", high: "D" }); - var r2 = new Range({ low: "B", high: "C" }); - assert(r1.intersect(r2)); - done(); - }); - - it("[nativeApi] B,C insersects A,D is true", function (done) { - var r1 = new Range({ low: "B", high: "C" }); - var r2 = new Range({ low: "A", high: "D" }); - assert(r1.intersect(r2)); - done(); - }); - - it("[nativeApi] A,C insersects B,D is true", function (done) { - var r1 = new Range({ low: "A", high: "C" }); - var r2 = new Range({ low: "B", high: "D" }); - assert(r1.intersect(r2)); - assert(r2.intersect(r1)); - done(); - }); - - it("[nativeApi] B,D insersects A,C is true", function (done) { - var r1 = new Range({ low: "B", high: "D" }); - var r2 = new Range({ low: "A", high: "C" }); - assert(r1.intersect(r2)); - done(); - }); - - it("[nativeApi] A,B insersects B,C is true", function (done) { - var r1 = new Range({ low: "A", high: "B" }); - var r2 = new Range({ low: "B", high: "C" }); - assert(r1.intersect(r2)); - assert(r2.intersect(r1)); - done(); - }); - - it("[nativeApi] B,C insersects A,B is true", function (done) { - var r1 = new Range({ low: "B", high: "C" }); - var r2 = new Range({ low: "A", high: "B" }); - assert(r1.intersect(r2)); - done(); - }); - - it("[nativeApi] A,B insersects C,D is false", function (done) { - var r1 = new Range({ low: "A", high: "B" }); - var r2 = new Range({ low: "C", high: "D" }); - assert(!r1.intersect(r2)); - done(); - }); - - it("[nativeApi] C,D insersects A,B is false", function (done) { - var r1 = new Range({ low: "C", high: "D" }); - var r2 = new Range({ low: "A", high: "B" }); - assert(!r1.intersect(r2)); - done(); - }); - }); - - describe("toString", function () { - var toStringTest = function (options, expectedString, done) { - var r = new Range(options); - assert.strictEqual(r.toString(), expectedString); - done(); - }; - - it("[nativeApi] undefined values", function (done) { - toStringTest(undefined, "undefined,undefined", done); - }); - it("[nativeApi] null values", function (done) { - toStringTest({ low: null }, "null,null", done); - }); - it("[nativeApi] NaN values", function (done) { - toStringTest({ low: NaN }, "NaN,NaN", done); - }); - it("[nativeApi] number values", function (done) { - toStringTest({ low: 1 }, "1,1", done); - }); - it("[nativeApi] string values", function (done) { - toStringTest({ low: "a" }, "a,a", done); - }); - it("[nativeApi] boolean values", function (done) { - toStringTest({ low: false, high: true }, "false,true", done); - }); - it("[nativeApi] object values", function (done) { - toStringTest({ low: {} }, "[object Object],[object Object]", done); - }); - }); - - describe("_compare", function () { - var r = new Range(); - - var rangeWithComparisonAsNumbers = new Range({ - compareFunction: function (a, b) { - return a - b; - } - }); - - var rangeWithConstantComparison = new Range({ - compareFunction: function (a, b) { - return 0; - } - }); - - - it("[nativeApi] _compare(undefined, undefined) === 0", function (done) { - assert(r._compare() === 0); - assert(r._compare(undefined) === 0); - assert(r._compare(undefined, undefined) === 0); - done(); - }); - - it("[nativeApi] _compare(undefined, y) > 0", function (done) { - assert(r._compare(undefined, null) > 0); - assert(r._compare(undefined, -NaN) > 0); - assert(r._compare(undefined, 0) > 0); - assert(r._compare(undefined, NaN) > 0); - assert(r._compare(undefined, true) > 0); - assert(r._compare(undefined, false) > 0); - assert(r._compare(undefined, "a") > 0); - assert(r._compare(undefined, "undefined") > 0); - assert(r._compare(undefined, "z") > 0); - assert(r._compare(undefined, []) > 0); - assert(r._compare(undefined, {}) > 0); - done(); - }); - - it("[nativeApi] _compare(x, undefined) < -1", function (done) { - assert(r._compare(null) < 0); - assert(r._compare(-NaN) < 0); - assert(r._compare(0) < 0); - assert(r._compare(NaN) < 0); - assert(r._compare(true) < 0); - assert(r._compare(false) < 0); - assert(r._compare("a") < 0); - assert(r._compare("undefined") < 0); - assert(r._compare("z") < 0); - assert(r._compare([]) < 0); - assert(r._compare({}) < 0); - done(); - }); - - it("[nativeApi] _compare values as strings (default)", function (done) { - assert(r._compare("A", "B") < 0); - assert(r._compare("", "") === 0); - assert(r._compare("B", "A") > 0); - assert(r._compare("10", "2") < 0); - assert(r._compare(10, "02") > 0); - assert(r._compare(10, 2) < 0); - assert(r._compare(null, "nulm") < 0); - assert(r._compare(null, "null") === 0); - assert(r._compare(null, "nulk") > 0); - assert(r._compare(true, "truf") < 0); - assert(r._compare(true, "true") === 0); - assert(r._compare(true, "trud") > 0); - assert(r._compare({}, "[object Object]") === 0); - done(); - }); - - it("[nativeApi] _compare values as numbers", function (done) { - assert(rangeWithComparisonAsNumbers._compare(undefined, 2) > 0); - assert(rangeWithComparisonAsNumbers._compare(1, 2) < 0); - assert(rangeWithComparisonAsNumbers._compare(0, 0) === 0); - assert(rangeWithComparisonAsNumbers._compare(10, 2) > 0); - done(); - }); - - it("[nativeApi] _compare always return 0", function (done) { - assert(rangeWithConstantComparison._compare(1, 2) === 0); - assert(rangeWithConstantComparison._compare(2, 1) === 0); - assert(rangeWithConstantComparison._compare(undefined, 2) > 0); - assert(rangeWithConstantComparison._compare(1, undefined) < 0); - - done(); - }); - }); - - describe("_isRange", function () { - it("[nativeApi] _isRange(undefined) is false", function (done) { - assert(!Range._isRange()); - done(); - }); - - it("[nativeApi] _isRange(null) is false", function (done) { - assert(!Range._isRange(null)); - done(); - }); - - it("[nativeApi] _isRange(non-object) is false", function (done) { - var points = [ - undefined, - null, - 1, - "", - true, - NaN, - function () { - }, - {}, - { - low: "" - } - ]; - - for (var i = 0; i < points.length; i++) { - assert(!Range._isRange(points[i])); - } - - done(); - }); - - it("[nativeApi] _isRange(point) is false", function (done) { - var ranges = [ - { - low: "", - high: 1 - }, - new Range() - ]; - - for (var i = 0; i < ranges.length; i++) { - assert(Range._isRange(ranges[i])); - } - - done(); - }); - }); - }); - - describe("RangePartitionResolver Tests", function () { - describe("constructor", function () { - it("[nativeApi] missing partitionKeyExtractor throws", function (done) { - var expetcedError = /Error: partitionKeyExtractor cannot be null or undefined/; - - assert.throws( - function () { - var r = new RangePartitionResolver(); - }, - expetcedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver(undefined); - }, - expetcedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver(null); - }, - expetcedError - ); - - done(); - }); - - it("[nativeApi] invalid partitionKeyExtractor throws", function (done) { - var expetcedError = /partitionKeyExtractor must be either a 'string' or a 'function'/; - - assert.throws( - function () { - var r = new RangePartitionResolver(0); - }, - expetcedError - ); - - assert.throws( - function () { - var r = RangePartitionResolver(true); - }, - expetcedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver(NaN); - }, - expetcedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver([]); - }, - expetcedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver({}); - }, - expetcedError - ); - - - done(); - }); - - it("[nativeApi] missing partitionKeyMap throws", function (done) { - var expectedError = /Error: partitionKeyMap cannot be null or undefined/; - - assert.throws( - function () { - var r = new RangePartitionResolver(""); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver(function () { - }); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver("", null); - }, - expectedError - ); - - done(); - }); - - it("[nativeApi] invalid partitionKeyMap throws", function (done) { - var expectedError = /Error: partitionKeyMap has to be an Array/; - - assert.throws( - function () { - var r = new RangePartitionResolver("", 0); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver("", ""); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver("", true); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver("", NaN); - }, - expectedError - ); - - assert.throws( - function () { - var r = new RangePartitionResolver("", {}); - }, - expectedError - ); - - var r = new RangePartitionResolver("", new Array()); - done(); - }); - - it("[nativeApi] valid RangePartitionResolver", function (done) { - var resolver = new RangePartitionResolver("", []); - assert(resolver); - assert.strictEqual(resolver.partitionKeyExtractor, ""); - assert.deepEqual(resolver.partitionKeyMap, []); - done(); - }); - }); - - describe("_getFirstContainingMapEntryOrNull", function () { - it("[nativeApi] _getFirstContainingMapEntryOrNull - empty map returns null", function (done) { - var ranges = [undefined, null, 0, "", true, [], {}, NaN, new Range()]; - var resolver = new RangePartitionResolver("", []); - ranges.forEach(function (r) { - var result = resolver._getFirstContainingMapEntryOrNull(r); - assert.equal(result, null); - }); - done(); - }); - - it("[nativeApi] _tryGetContainingRange - map with no containing entry returns null", function (done) { - var mapEntry = { range: new Range({ low: "A" }), link: "link1" }; - var resolver = new RangePartitionResolver("key", [mapEntry]); - var result = resolver._getFirstContainingMapEntryOrNull(new Range({ low: "B" })); - assert.equal(result, null); - done(); - }); - - it("[nativeApi] _tryGetContainingRange - map with single containing entry returns entry", function (done) { - var mapEntry = { range: new Range(), link: "link1" }; - var resolver = new RangePartitionResolver("key", [mapEntry]); - var result = resolver._getFirstContainingMapEntryOrNull(new Range()); - assert.deepEqual(result, { range: new Range(), link: "link1" }); - done(); - }); - - it("[nativeApi] _tryGetContainingRange - map with more multiple containing entries returns first entry", function (done) { - var map1 = [ - { range: new Range({ low: "A", high: "B" }), link: "link1" }, - { range: new Range({ low: "A" }), link: "link2" } - ]; - - var resolver1 = new RangePartitionResolver("key", map1); - var result1 = resolver1._getFirstContainingMapEntryOrNull(new Range({ low: "A" })); - assert.strictEqual(result1.link, "link1"); - - var map2 = [ - { range: new Range({ low: "A" }), link: "link2" }, - { range: new Range({ low: "A", high: "Z" }), link: "link1" } - ]; - - var resolver2 = new RangePartitionResolver("key", map2); - var result2 = resolver2._getFirstContainingMapEntryOrNull(new Range({ low: "A" })); - assert.strictEqual(result2.link, "link2"); - done(); - }); - }); - - describe("resolveForCreate", function () { - it("[nativeApi] _tryGetContainingRange - map containing parition key returns corresponding link", function (done) { - var resolver = new RangePartitionResolver("key", [ - { range: new Range({ low: "A", high: "M" }), link: "link1" }, - { range: new Range({ low: "N", high: "Z" }), link: "link2" } - ]); - var result = resolver.resolveForCreate("X"); - assert.strictEqual(result, "link2"); - done(); - }); - - it("[nativeApi] _tryGetContainingRange - map not containing parition key throws", function (done) { - var resolver = new RangePartitionResolver("key", [ - { range: new Range({ low: "A", high: "M" }), link: "link1" } - ]); - - assert.throws( - function () { - var result = resolver.resolveForCreate("X"); - }, - /Error: Invalid operation: A containing range for 'X,X' doesn't exist in the partition map./ - ); - done(); - }); - }); - }); - - describe("HashPartitionResolver Tests", function () { + describe("HashPartitionResolver", function () { var test = function (useUpsert, done) { var client = new DocumentDBClient(host, { masterKey: masterKey }); @@ -3273,7 +2331,7 @@ describe("NodeJS CRUD Tests", function() { }); }; - it("[promiseApi] Should do document CRUD operations with a partition resolver successfully", function (done) { test(false, done) }); - it("[promiseApi] Should do document CRUD operations with a partition resolver successfully with upsert", function (done) { test(true, done) }); + it("CRUD operations", function (done) { test(false, done) }); + it("CRUD operations with upsert", function (done) { test(true, done) }); }); -}); +}); \ No newline at end of file