- Fixed RangePartitionResolver.resolveForRead bug where it was not returning links due to a bad concat of results
- Move compareFunction from Range class to RangePartitionResolver class
This commit is contained in:
Armando Trejo 2016-03-07 17:23:50 -08:00
Родитель efa1e081ab
Коммит 59c1e06948
17 изменённых файлов: 1338 добавлений и 1143 удалений

5
source/.gitignore поставляемый
Просмотреть файл

@ -1,8 +1,5 @@
*.csproj
*.njsproj
generateDocs.cmd
RunFunctionalTests.cmd
runtests.cmd
*.cmd
config.js
.vs/

Просмотреть файл

@ -3,24 +3,24 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{21b5837f-38c5-4c27-9cce-7dcb27eeda3f}</ProjectGuid>
<ProjectGuid>{411c2c02-66ef-40c8-a964-af8fdacf3961}</ProjectGuid>
<StartupFile>test\test.js</StartupFile>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<StartWebBrowser>True</StartWebBrowser>
<UseIISExpress>true</UseIISExpress>
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
<ItemGroup>
<Content Include="package.json" />
<Content Include="changelog.md" />
<Content Include="readme.md" />
<Content Include="readme.html" />
<Content Include="test\readme.md" />
</ItemGroup>
<ItemGroup>
@ -49,6 +49,15 @@
<Compile Include="test\consistentHashRingTests.js">
<TestFramework>Mocha</TestFramework>
</Compile>
<Compile Include="test\documentClientTests.js">
<TestFramework>Mocha</TestFramework>
</Compile>
<Compile Include="test\rangeTests.js">
<TestFramework>Mocha</TestFramework>
</Compile>
<Compile Include="test\rangePartitionResolverTests.js">
<TestFramework>Mocha</TestFramework>
</Compile>
<Compile Include="test\murmurHashTests.js">
<TestFramework>Mocha</TestFramework>
</Compile>
@ -59,29 +68,31 @@
<None Include=".editorconfig" />
<None Include=".eslintrc" />
<None Include="package.json" />
<None Include="readme.md" />
<None Include="readme.html" />
<None Include="changelog.md" />
<None Include="test\readme.md" />
</ItemGroup>
<ItemGroup>
<Folder Include="lib\" />
<Folder Include="lib\hash\" />
<Folder Include="lib" />
<Folder Include="lib\hash" />
<Folder Include="test" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<!--Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them.-->
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:39938/</IISUrl>
<IISUrl>http://localhost:48022/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
@ -102,7 +113,7 @@
</StartCmdLineArguments>
<StartWorkingDirectory>
</StartWorkingDirectory>
<EnableENC>True</EnableENC>
<EnableENC>False</EnableENC>
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
</WebProjectProperties>
</FlavorProperties>

Просмотреть файл

@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "DocumentDB", "DocumentDB.njsproj", "{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}"
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "DocumentDB.Node.master", "DocumentDB.Node.master.njsproj", "{411C2C02-66EF-40C8-A964-AF8FDACF3961}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -11,10 +11,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Debug|Any CPU.Build.0 = Release|Any CPU
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Release|Any CPU.Build.0 = Release|Any CPU
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Debug|Any CPU.Build.0 = Debug|Any CPU
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Release|Any CPU.ActiveCfg = Release|Any CPU
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -1,3 +1,8 @@
## Changes in 1.5.6 : ##
- Fixed RangePartitionResolver.resolveForRead bug where it was not returning links due to a bad concat of results
- Move compareFunction from Range class to RangePartitionResolver class
## Changes in 1.5.5 : ##
- Fixed hashParitionResolver resolveForRead(): When no partition key supplied was throwing exception, instead of returning a list of all registered links.

Просмотреть файл

@ -146,7 +146,7 @@ var Constants = {
CurrentVersion: "2015-08-06",
UserAgent: "documentdb-nodejs-sdk-1.5.5",
UserAgent: "documentdb-nodejs-sdk-1.5.6",
DefaultPrecisions: {
DefaultNumberHashPrecision: 3,

Просмотреть файл

@ -33,7 +33,6 @@ var Range = Base.defineClass(
* @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) {
@ -50,80 +49,11 @@ var Range = Base.defineClass(
}
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
* @memberof Range
* @instance
* @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
* @memberof Range
* @instance
* @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.
* @memberof Range
* @instance
* @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"
* @memberof Range
* @instance
* @returns {string} - Returns a string representation of the range.
**/
toString: function () {
return String(this.low) + "," + String(this.high);
},
/** @ignore */
_compare: function (x, y) {
_compare: function (x, y, compareFunction) {
// Same semantics as Array.sort
// http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare
if (x === undefined && y === undefined)
@ -132,8 +62,8 @@ var Range = Base.defineClass(
return 1;
if (y === undefined)
return -1;
if (this.compareFunction !== undefined) {
var v = Number(this.compareFunction(x, y));
if (compareFunction !== undefined) {
var v = Number(compareFunction(x, y));
if (v === NaN)
return 0;
return v;
@ -148,16 +78,39 @@ var Range = Base.defineClass(
},
/** @ignore */
_containsPoint: function (point) {
if (this._compare(point, this.low) >= 0 && this._compare(point, this.high) <= 0) {
_contains: function (other, compareFunction) {
if (Range._isRange(other)) {
return this._containsRange(other, compareFunction);
}
else {
return this._containsPoint(other, compareFunction);
}
},
/** @ignore */
_containsPoint: function (point, compareFunction) {
if (this._compare(point, this.low, compareFunction) >= 0 && this._compare(point, this.high, compareFunction) <= 0) {
return true;
}
return false;
},
/** @ignore */
_containsRange: function (other) {
if (this._compare(other.low, this.low) >= 0 && this._compare(other.high, this.high) <= 0) {
_containsRange: function (other, compareFunction) {
if (this._compare(other.low, this.low, compareFunction) >= 0 && this._compare(other.high, this.high, compareFunction) <= 0) {
return true;
}
return false;
},
/** @ignore */
_intersect: function (other, compareFunction) {
if (other === undefined || other === null) {
throw new Error("Invalid Argument: 'other' is undefined or null");
}
var maxLow = this._compare(this.low, other.low, compareFunction) >= 0 ? this.low : other.low;
var minHigh = this._compare(this.high, other.high, compareFunction) <= 0 ? this.high : other.high;
if (this._compare(maxLow, minHigh, compareFunction) <= 0) {
return true;
}
return false;
@ -180,6 +133,11 @@ var Range = Base.defineClass(
this._state = this._states.ended;
callback(undefined, this.resources, this.resHeaders);
}
},
/** @ignore */
_toString: function () {
return String(this.low) + "," + String(this.high);
}
},
{
@ -206,8 +164,9 @@ var RangePartitionResolver = Base.defineClass(
* @param {string | 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 an object.
* @param {Array} partitionKeyMap - The map from Range to collection link that is used for partitioning requests.
* @param {function} 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(partitionKeyExtractor, partitionKeyMap) {
function(partitionKeyExtractor, partitionKeyMap, compareFunction) {
if (partitionKeyExtractor === undefined || partitionKeyExtractor === null) {
throw new Error("partitionKeyExtractor cannot be null or undefined");
}
@ -241,8 +200,13 @@ var RangePartitionResolver = Base.defineClass(
if (!allMapEntriesAreValid) {
throw new Error("All partitionKeyMap entries have to be a tuple {range: Range, link: string }");
}
if (compareFunction !== undefined && typeof compareFunction !== "function") {
throw new Error("Invalid argument: 'compareFunction' is not a function");
}
this.partitionKeyExtractor = partitionKeyExtractor;
this.partitionKeyMap = partitionKeyMap;
this.compareFunction = compareFunction;
}, {
/**
* Extracts the partition key from the specified document using the partitionKeyExtractor
@ -274,7 +238,7 @@ var RangePartitionResolver = Base.defineClass(
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.");
throw new Error("Invalid operation: A containing range for '" + range._toString() + "' doesn't exist in the partition map.");
},
/**
@ -295,7 +259,8 @@ var RangePartitionResolver = Base.defineClass(
/** @ignore */
_getFirstContainingMapEntryOrNull: function (point) {
var containingMapEntries = this.partitionKeyMap.filter(function (p) { return p.range !== undefined && p.range.contains(point); });
var _this = this;
var containingMapEntries = this.partitionKeyMap.filter(function (p) { return p.range !== undefined && p.range._contains(point, _this.compareFunction); });
if (containingMapEntries && containingMapEntries.length > 0) {
return containingMapEntries[0];
}
@ -306,10 +271,12 @@ var RangePartitionResolver = Base.defineClass(
_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 ranges = partitionKeys.map(function (p) { return Range._isRange(p) ? p : new Range({ low: p }); });
var result = new Array();
ranges.forEach(function (range) {
result.concat(_this.partitionKeyMap.filter(function (entry) { return entry.range.intersect(range); }));
result = result.concat(_this.partitionKeyMap.filter(function (entry) {
return entry.range._intersect(range, _this.compareFunction);
}));
});
return result;
}

Просмотреть файл

@ -9,7 +9,7 @@
"database",
"cloud"
],
"version": "1.5.5",
"version": "1.5.6",
"author": "Microsoft Corporation",
"main": "./index.js",
"engine": {

42
source/readme.html Normal file
Просмотреть файл

@ -0,0 +1,42 @@
<html>
<head>
<title>Windows Azure DocumentDB SDK: node.js</title>
</head>
<body>
<h1>Windows Azure DocumentDB Node.js SDK</h1>
<p>
This project provides a node module that makes it easy to interact with Azure DocumentDB. For documentation please see the <a href="https://azure.microsoft.com/en-us/documentation/articles/documentdb-sdk-node/" target="_blank">Microsoft Azure DocumentDB Node.js SDK Documentation</a>.
</p>
<h2>Installation</h2><h4>Core Module</h4><p>The core module uses the callbacks model for responses, exposed through the DocumentClient </p>
<pre class="prettyprint source"><code>npm install documentdb</code></pre>
<h2>Usage</h2>
<p>To use this SDK to call Azure DocumentDB, you need to first <a href="http://azure.microsoft.com/en-us/documentation/articles/documentdb-create-account/" target="_blank">create an account</a>.</p>
<p>You can follow this <a href="http://azure.microsoft.com/en-us/documentation/articles/documentdb-nodejs-application/" target="_blank">tutorial</a> to help you get started.</p>
<h2>Examples</h2><h4>Hello World using Callbacks via the Core Module</h4><pre class="prettyprint source lang-js"><code>var DocumentClient = require('documentdb').DocumentClient;
var host = &quot;[hostendpoint]&quot;; // Add your endpoint
var masterKey = &quot;[database account masterkey]&quot;; // Add the massterkey of the endpoint
var client = new DocumentClient(host, {masterKey: masterKey});
var databaseDefinition = { id: &quot;sample database&quot; };
var collectionDefinition = { id: &quot;sample collection&quot; };
var documentDefinition = { id: &quot;hello world doc&quot;, content: &quot;Hello World!&quot; };
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);
})
}</code></pre>
</body>
</html>

Просмотреть файл

@ -1,56 +0,0 @@
<html>
<head>
<title>Windows Azure DocumentDB SDK: node.js</title>
</head>
<body>
<h2>Windows Azure DocumentDB nodejs SDK</h2>
<p>
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, <br>
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 <br>
processing capabilities that scale to meet the needs of the most demanding modern applications.
</p>
<p>
The Nodejs sdk uses callbacks model for responses and this is exposed in DocumentClient <br>
</p>
<h4>Installing the library using npm</h4>
<p><pre>&gt; npm install documentdb</pre></p>
<h4>Hello world example code using callbacks</h4>
<p><pre style="background-color:#eee">
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);
})
}
</pre></p>
##Community
- [DoQmentDB](https://github.com/a8m/doqmentdb) - A Promise-based DocumentDB client for MongoDB users

Просмотреть файл

@ -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 () {

Просмотреть файл

@ -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();
});
});
});

Просмотреть файл

@ -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 () {

Просмотреть файл

@ -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 () {

Просмотреть файл

@ -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();
});
});
});

502
source/test/rangeTests.js Normal file
Просмотреть файл

@ -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();
});
});
});

Просмотреть файл

@ -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) });
});
});