diff --git a/source/DocumentDB.njsproj b/source/DocumentDB.njsproj
index f38aef0..9f642ec 100644
--- a/source/DocumentDB.njsproj
+++ b/source/DocumentDB.njsproj
@@ -37,6 +37,7 @@
+
diff --git a/source/Gruntfile.js b/source/Gruntfile.js
index 2918f19..8dc4034 100644
--- a/source/Gruntfile.js
+++ b/source/Gruntfile.js
@@ -1,3 +1,26 @@
+/*
+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";
module.exports = function (grunt) {
diff --git a/source/index.js b/source/index.js
index a162f3a..d72aa83 100644
--- a/source/index.js
+++ b/source/index.js
@@ -1 +1,24 @@
+/*
+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.
+*/
+
module.exports = require('./lib/');
\ No newline at end of file
diff --git a/source/lib/auth.js b/source/lib/auth.js
index bb433d8..fecb53a 100644
--- a/source/lib/auth.js
+++ b/source/lib/auth.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/lib/base.js b/source/lib/base.js
index cd1536a..c5025c4 100644
--- a/source/lib/base.js
+++ b/source/lib/base.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/lib/constants.js b/source/lib/constants.js
index 2111635..1e4bb3e 100644
--- a/source/lib/constants.js
+++ b/source/lib/constants.js
@@ -1,6 +1,26 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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.
+*/
+
//SCRIPT START
diff --git a/source/lib/documentclient.js b/source/lib/documentclient.js
index c3051c5..55cc3a0 100644
--- a/source/lib/documentclient.js
+++ b/source/lib/documentclient.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/lib/documents.js b/source/lib/documents.js
index 0eca635..5d10b05 100644
--- a/source/lib/documents.js
+++ b/source/lib/documents.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/lib/index.js b/source/lib/index.js
index 3abf2db..c8f73e1 100644
--- a/source/lib/index.js
+++ b/source/lib/index.js
@@ -1,10 +1,36 @@
+/*
+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 Client = require("./documentclient");
+var Client = require("./documentclient")
+ , Range = require("./range");
if (typeof exports !== "undefined") {
exports.DocumentClient = Client.DocumentClient;
exports.DocumentBase = Client.DocumentBase;
exports.Base = Client.Base;
exports.Constants = Client.Constants;
+ exports.Range = Range.Range;
+ exports.RangePartitionResolver = Range.RangePartitionResolver;
}
\ No newline at end of file
diff --git a/source/lib/queryIterator.js b/source/lib/queryIterator.js
index 329ed02..7341a9e 100644
--- a/source/lib/queryIterator.js
+++ b/source/lib/queryIterator.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/lib/range.js b/source/lib/range.js
new file mode 100644
index 0000000..a5e7531
--- /dev/null
+++ b/source/lib/range.js
@@ -0,0 +1,308 @@
+/*
+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 Base = require("./base");
+
+//SCRIPT START
+var Range = Base.defineClass(
+ /**
+ * Represents a range object used by the RangePartitionResolver
+ * @constructor Range
+ * @param {object} options - The Range constructor options.
+ * @param {any} options.low - The low value in the range.
+ * @param {any} options.high - The high value in the range.
+ * @param {function} options.compareFunction - Optional function that accepts two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.
+ **/
+ function(options) {
+ if (options === undefined) {
+ options = {};
+ }
+ if (options === null) {
+ throw new Error("Invalid argument: 'options' is null");
+ }
+ if (typeof options !== "object") {
+ throw new Error("Invalid argument: 'options' is not an object");
+ }
+ if (options.high === undefined) {
+ options.high = options.low;
+ }
+ this.low = options.low;
+ this.high = options.high;
+ this.compareFunction = options.compareFunction;
+ if (this.compareFunction !== undefined && typeof this.compareFunction !== "function") {
+ throw new Error("Invalid argument: 'options.compareFunction' is not a function");
+ }
+ if (this._compare(this.low, this.high) > 0) {
+ throw new Error("Invalid argument: 'options.low' must be less than or equal than 'options.high'");
+ }
+ Object.freeze(this);
+ },
+ {
+ /**
+ * Compares two ranges
+ * @param {object} other - The input range to be compared with this range.
+ * @returns {number} - A negative value if this < other zero if this = other, or a positive value if this > other.
+ **/
+ compareTo: function(other) {
+ if (this._compare(this.low, other.low) === 0 && this._compare(this.high, other.high) === 0) {
+ return 0;
+ }
+ if (this._compare(this.low, other.low) < 0 || this._compare(this.high, other.high) < 0) {
+ return -1;
+ }
+ return 1;
+ },
+
+ /**
+ * Check for containment of the other range in this range
+ * @param {object} other - The key or range to be checked if in this range.
+ * @returns {boolean} - Returns true if the input is contained in this range; false otherwise.
+ **/
+ contains: function (other) {
+ if (Range._isRange(other)) {
+ return this._containsRange(other);
+ }
+ else {
+ return this._containsPoint(other);
+ }
+ },
+
+ /**
+ * Checks if the other range intersects with this range.
+ * @param {object} other - The input range to be checked for intersection with this range.
+ * @returns {boolean} - Returns true if the two ranges intersect with each other; false otherwise.
+ **/
+ intersect: function (other) {
+ if (other === undefined || other === null) {
+ throw new Error("Invalid Argument: 'other' is undefined or null");
+ }
+ var maxLow = this._compare(this.low, other.low) >= 0 ? this.low : other.low;
+ var minHigh = this._compare(this.high, other.high) <= 0 ? this.high : other.high;
+ if (this._compare(maxLow, minHigh) <= 0) {
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Converts the range to a string in the form of "low,high"
+ * @returns {string} - Returns a string representation of the range.
+ **/
+ toString: function () {
+ return String(this.low) + "," + String(this.high);
+ },
+
+ /** @ignore */
+ _compare: function (x, y) {
+ // Same semantics as Array.sort
+ // http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare
+ if (x === undefined && y === undefined)
+ return 0;
+ if (x === undefined)
+ return 1;
+ if (y === undefined)
+ return -1;
+ if (this.compareFunction !== undefined) {
+ var v = Number(this.compareFunction(x, y));
+ if (v === NaN)
+ return 0;
+ return v;
+ }
+ var xString = String(x);
+ var yString = String(y);
+ if (xString < yString)
+ return -1;
+ if (xString > yString)
+ return 1;
+ return 0;
+ },
+
+ /** @ignore */
+ _containsPoint: function (point) {
+ if (this._compare(point, this.low) >= 0 && this._compare(point, this.high) <= 0) {
+ return true;
+ }
+ return false;
+ },
+
+ /** @ignore */
+ _containsRange: function (other) {
+ if (this._compare(other.low, this.low) >= 0 && this._compare(other.high, this.high) <= 0) {
+ return true;
+ }
+ return false;
+ },
+
+ /** @ignore */
+ _toArrayImplementation: function(callback){
+ var that = this;
+ if (this._canFetchMore()) {
+ this._fetchMore(function(err, resources, headers){
+ if(err) {
+ return callback(err, undefined, headers);
+ }
+
+ that.resHeaders = headers;
+ that.resources = that.resources.concat(resources);
+ that._toArrayImplementation(callback);
+ });
+ } else {
+ this._state = this._states.ended;
+ callback(undefined, this.resources, this.resHeaders);
+ }
+ }
+ },
+ {
+ /** @ignore */
+ _isRange: function (pointOrRange) {
+ if (pointOrRange === undefined) {
+ return false;
+ }
+ if (pointOrRange === null) {
+ return false;
+ }
+ if (typeof pointOrRange !== "object") {
+ return false;
+ }
+ return ("low" in pointOrRange && "high" in pointOrRange);
+ }
+ }
+);
+
+var RangePartitionResolver = Base.defineClass(
+ /**
+ * RangePartitionResolver implements partitioning using a partition map of ranges of values to a collection link.
+ * @param {string or function} partitionKeyExtractor - If partitionKeyExtractor is a string, it should be the name of the property in the document to execute the hashing on.
+ * If partitionKeyExtractor is a function, it should be a function to extract the partition key from any object.
+ * @param {Array} partitionKeyMap - The map from range to collection-link that is used for partitioning requests.
+ **/
+ function(partitionKeyExtractor, partitionKeyMap) {
+ if (partitionKeyExtractor === undefined || partitionKeyExtractor === null) {
+ throw new Error("partitionKeyExtractor cannot be null or undefined");
+ }
+ if (typeof partitionKeyExtractor !== "string" && typeof partitionKeyExtractor !== "function") {
+ throw new Error("partitionKeyExtractor has to have 'string' or 'function' type.");
+ }
+ if (partitionKeyMap === undefined || partitionKeyMap === null) {
+ throw new Error("partitionKeyMap cannot be null or undefined");
+ }
+ if (!(Array.isArray(partitionKeyMap))) {
+ throw new Error("partitionKeyMap has to be an Array");
+ }
+ var allMapEntriesAreValid = partitionKeyMap.every(function (mapEntry) {
+ if ((mapEntry === undefined) || mapEntry === null) {
+ return false;
+ }
+ if (mapEntry.range === undefined) {
+ return false;
+ }
+ if (!(mapEntry.range instanceof Range)) {
+ return false;
+ }
+ if (mapEntry.link === undefined) {
+ return false;
+ }
+ if (typeof mapEntry.link !== "string") {
+ return false;
+ }
+ return true;
+ });
+ if (!allMapEntriesAreValid) {
+ throw new Error("All partitionKeyMap entries have to be a tuple {range: Range, link: string }");
+ }
+ this.partitionKeyExtractor = partitionKeyExtractor;
+ this.partitionKeyMap = partitionKeyMap;
+ }, {
+ /**
+ * Extracts the partition key from the specified document using the partitionKeyExtractor
+ * @param {object} document - The document from which to extract the partition key.
+ * @returns {}
+ **/
+ getPartitionKey: function (document) {
+ if (typeof this.partitionKeyExtractor === "string") {
+ return document[this.partitionKeyExtractor];
+ }
+ if (typeof this.partitionKeyExtractor === "function") {
+ return this.partitionKeyExtractor(document);
+ }
+ throw new Error("Unable to extract partition key from document. Ensure PartitionKeyExtractor is a valid function or property name.");
+ },
+
+ /**
+ * Given a partition key, returns the correct collection link for creating a document using the range partition map.
+ * @param {any} partitionKey - The partition key used to determine the target collection for create
+ * @returns {string} - The target collection link that will be used for document creation.
+ **/
+ resolveForCreate: function (partitionKey) {
+ var range = new Range({ low: partitionKey });
+ var mapEntry = this._getFirstContainingMapEntryOrNull(range);
+ if (mapEntry !== undefined && mapEntry !== null) {
+ return mapEntry.link;
+ }
+ throw new Error("Invalid operation: A containing range for '" + range.toString() + "' doesn't exist in the partition map.");
+ },
+
+ /**
+ * Given a partition key, returns a list of collection links to read from using the range partition map.
+ * @param {any} partitionKey - The partition key used to determine the target collection for query
+ * @returns {string[]} - The list of target collection links.
+ **/
+ resolveForRead: function (partitionKey) {
+ if (partitionKey === undefined || partitionKey === null) {
+ return this.partitionKeyMap.map(function (i) { return i.link; });
+ }
+ else {
+ return this._getIntersectingMapEntries(partitionKey).map(function (i) { return i.link; });
+ }
+ },
+
+ /** @ignore */
+ _getFirstContainingMapEntryOrNull: function (point) {
+ var containingMapEntries = this.partitionKeyMap.filter(function (p) { return p.range !== undefined && p.range.contains(point); });
+ if (containingMapEntries && containingMapEntries.length > 0) {
+ return containingMapEntries[0];
+ }
+ return null;
+ },
+
+ /** @ignore */
+ _getIntersectingMapEntries: function (partitionKey) {
+ var _this = this;
+ var partitionKeys = (partitionKey instanceof Array) ? partitionKey : [partitionKey];
+ var ranges = partitionKeys.map(function (p) { return Range._isRange(p) ? p : new Range(p); });
+ var result = new Array();
+ ranges.forEach(function (range) {
+ result.concat(_this.partitionKeyMap.filter(function (entry) { return entry.range.intersect(range); }));
+ });
+ return result;
+ }
+ }
+);
+//SCRIPT END
+
+if (typeof exports !== "undefined") {
+ exports.Range = Range;
+ exports.RangePartitionResolver = RangePartitionResolver;
+}
\ No newline at end of file
diff --git a/source/lib/request.js b/source/lib/request.js
index 2ec94bb..21d0301 100644
--- a/source/lib/request.js
+++ b/source/lib/request.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
diff --git a/source/test/_testConfig.js b/source/test/_testConfig.js
index f24a4b4..53c2586 100644
--- a/source/test/_testConfig.js
+++ b/source/test/_testConfig.js
@@ -1,5 +1,28 @@
-var host = "MyHost";
-var key = "MyKey";
+/*
+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.
+*/
+
+var masterKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
+var host = "https://localhost:443";
exports.host = host;
-exports.masterKey = key;
+exports.masterKey = masterKey;
diff --git a/source/test/test.js b/source/test/test.js
index d845f14..d48d206 100644
--- a/source/test/test.js
+++ b/source/test/test.js
@@ -1,6 +1,25 @@
-//----------------------------------------------------------------------------
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//----------------------------------------------------------------------------
+/*
+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";
@@ -10,7 +29,9 @@ var Base = require("documentdb").Base
, Constants = require("documentdb").Constants
, assert = require("assert")
, testConfig = require("./_testConfig")
- , Stream = require("stream");
+ , Stream = require("stream")
+ , Range = require("documentdb").Range
+ , RangePartitionResolver = require("documentdb").RangePartitionResolver;
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
@@ -2477,4 +2498,740 @@ describe("NodeJS CRUD Tests", function() {
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 \[object Object\]/
+ );
+
+ 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 = /Error: partitionKeyExtractor has to have 'string' or 'function' type/;
+
+ 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();
+ });
+ });
+ });
});