Version 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
This commit is contained in:
Родитель
efa1e081ab
Коммит
59c1e06948
|
@ -1,8 +1,5 @@
|
||||||
*.csproj
|
*.csproj
|
||||||
*.njsproj
|
*.cmd
|
||||||
generateDocs.cmd
|
|
||||||
RunFunctionalTests.cmd
|
|
||||||
runtests.cmd
|
|
||||||
|
|
||||||
config.js
|
config.js
|
||||||
.vs/
|
.vs/
|
||||||
|
|
|
@ -3,24 +3,24 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
<ProjectGuid>{21b5837f-38c5-4c27-9cce-7dcb27eeda3f}</ProjectGuid>
|
<ProjectGuid>{411c2c02-66ef-40c8-a964-af8fdacf3961}</ProjectGuid>
|
||||||
<StartupFile>test\test.js</StartupFile>
|
<StartupFile>test\test.js</StartupFile>
|
||||||
<WorkingDirectory>.</WorkingDirectory>
|
<WorkingDirectory>.</WorkingDirectory>
|
||||||
<OutputPath>.</OutputPath>
|
<OutputPath>.</OutputPath>
|
||||||
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
|
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
<StartWebBrowser>True</StartWebBrowser>
|
|
||||||
<UseIISExpress>true</UseIISExpress>
|
|
||||||
<SccProjectName>SAK</SccProjectName>
|
<SccProjectName>SAK</SccProjectName>
|
||||||
<SccProvider>SAK</SccProvider>
|
<SccProvider>SAK</SccProvider>
|
||||||
<SccAuxPath>SAK</SccAuxPath>
|
<SccAuxPath>SAK</SccAuxPath>
|
||||||
<SccLocalPath>SAK</SccLocalPath>
|
<SccLocalPath>SAK</SccLocalPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="package.json" />
|
<Content Include="package.json" />
|
||||||
<Content Include="changelog.md" />
|
<Content Include="changelog.md" />
|
||||||
<Content Include="readme.md" />
|
<Content Include="readme.html" />
|
||||||
<Content Include="test\readme.md" />
|
<Content Include="test\readme.md" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -49,6 +49,15 @@
|
||||||
<Compile Include="test\consistentHashRingTests.js">
|
<Compile Include="test\consistentHashRingTests.js">
|
||||||
<TestFramework>Mocha</TestFramework>
|
<TestFramework>Mocha</TestFramework>
|
||||||
</Compile>
|
</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">
|
<Compile Include="test\murmurHashTests.js">
|
||||||
<TestFramework>Mocha</TestFramework>
|
<TestFramework>Mocha</TestFramework>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -59,29 +68,31 @@
|
||||||
<None Include=".editorconfig" />
|
<None Include=".editorconfig" />
|
||||||
<None Include=".eslintrc" />
|
<None Include=".eslintrc" />
|
||||||
<None Include="package.json" />
|
<None Include="package.json" />
|
||||||
<None Include="readme.md" />
|
<None Include="readme.html" />
|
||||||
<None Include="changelog.md" />
|
<None Include="changelog.md" />
|
||||||
<None Include="test\readme.md" />
|
<None Include="test\readme.md" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="lib\" />
|
<Folder Include="lib" />
|
||||||
<Folder Include="lib\hash\" />
|
<Folder Include="lib\hash" />
|
||||||
<Folder Include="test" />
|
<Folder Include="test" />
|
||||||
</ItemGroup>
|
</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" />
|
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<VisualStudio>
|
<VisualStudio>
|
||||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||||
<WebProjectProperties>
|
<WebProjectProperties>
|
||||||
<UseIIS>True</UseIIS>
|
<UseIIS>False</UseIIS>
|
||||||
<AutoAssignPort>True</AutoAssignPort>
|
<AutoAssignPort>True</AutoAssignPort>
|
||||||
<DevelopmentServerPort>0</DevelopmentServerPort>
|
<DevelopmentServerPort>0</DevelopmentServerPort>
|
||||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||||
<IISUrl>http://localhost:39938/</IISUrl>
|
<IISUrl>http://localhost:48022/</IISUrl>
|
||||||
<NTLMAuthentication>False</NTLMAuthentication>
|
<NTLMAuthentication>False</NTLMAuthentication>
|
||||||
<UseCustomServer>False</UseCustomServer>
|
<UseCustomServer>True</UseCustomServer>
|
||||||
<CustomServerUrl>
|
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
|
||||||
</CustomServerUrl>
|
|
||||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||||
</WebProjectProperties>
|
</WebProjectProperties>
|
||||||
</FlavorProperties>
|
</FlavorProperties>
|
||||||
|
@ -102,7 +113,7 @@
|
||||||
</StartCmdLineArguments>
|
</StartCmdLineArguments>
|
||||||
<StartWorkingDirectory>
|
<StartWorkingDirectory>
|
||||||
</StartWorkingDirectory>
|
</StartWorkingDirectory>
|
||||||
<EnableENC>True</EnableENC>
|
<EnableENC>False</EnableENC>
|
||||||
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
|
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
|
||||||
</WebProjectProperties>
|
</WebProjectProperties>
|
||||||
</FlavorProperties>
|
</FlavorProperties>
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.23107.0
|
VisualStudioVersion = 14.0.24720.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -11,10 +11,10 @@ Global
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Debug|Any CPU.Build.0 = Release|Any CPU
|
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{21B5837F-38C5-4C27-9CCE-7DCB27EEDA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{411C2C02-66EF-40C8-A964-AF8FDACF3961}.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}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
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 : ##
|
## 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.
|
- Fixed hashParitionResolver resolveForRead(): When no partition key supplied was throwing exception, instead of returning a list of all registered links.
|
||||||
|
|
|
@ -38,7 +38,7 @@ var Constants = {
|
||||||
TextPlain: "text/plain",
|
TextPlain: "text/plain",
|
||||||
Xml: "application/xml"
|
Xml: "application/xml"
|
||||||
},
|
},
|
||||||
|
|
||||||
HttpMethods: {
|
HttpMethods: {
|
||||||
Get: "GET",
|
Get: "GET",
|
||||||
Post: "POST",
|
Post: "POST",
|
||||||
|
@ -47,7 +47,7 @@ var Constants = {
|
||||||
Head: "HEAD",
|
Head: "HEAD",
|
||||||
Options: "OPTIONS"
|
Options: "OPTIONS"
|
||||||
},
|
},
|
||||||
|
|
||||||
HttpHeaders: {
|
HttpHeaders: {
|
||||||
Authorization: "authorization",
|
Authorization: "authorization",
|
||||||
ETag: "etag",
|
ETag: "etag",
|
||||||
|
@ -95,15 +95,15 @@ var Constants = {
|
||||||
Prefer: "Prefer",
|
Prefer: "Prefer",
|
||||||
Location: "Location",
|
Location: "Location",
|
||||||
Referer: "referer",
|
Referer: "referer",
|
||||||
|
|
||||||
// Query
|
// Query
|
||||||
Query: "x-ms-documentdb-query",
|
Query: "x-ms-documentdb-query",
|
||||||
IsQuery: "x-ms-documentdb-isquery",
|
IsQuery: "x-ms-documentdb-isquery",
|
||||||
|
|
||||||
// Our custom DocumentDB headers
|
// Our custom DocumentDB headers
|
||||||
Continuation: "x-ms-continuation",
|
Continuation: "x-ms-continuation",
|
||||||
PageSize: "x-ms-max-item-count",
|
PageSize: "x-ms-max-item-count",
|
||||||
|
|
||||||
// Request sender generated. Simply echoed by backend.
|
// Request sender generated. Simply echoed by backend.
|
||||||
ActivityId: "x-ms-activity-id",
|
ActivityId: "x-ms-activity-id",
|
||||||
PreTriggerInclude: "x-ms-documentdb-pre-trigger-include",
|
PreTriggerInclude: "x-ms-documentdb-pre-trigger-include",
|
||||||
|
@ -123,7 +123,7 @@ var Constants = {
|
||||||
EmitVerboseTracesInQuery: "x-ms-documentdb-query-emit-traces",
|
EmitVerboseTracesInQuery: "x-ms-documentdb-query-emit-traces",
|
||||||
// Version headers and values
|
// Version headers and values
|
||||||
Version: "x-ms-version",
|
Version: "x-ms-version",
|
||||||
|
|
||||||
//Quota Info
|
//Quota Info
|
||||||
MaxEntityCount: "x-ms-root-entity-max-count",
|
MaxEntityCount: "x-ms-root-entity-max-count",
|
||||||
CurrentEntityCount: "x-ms-root-entity-current-count",
|
CurrentEntityCount: "x-ms-root-entity-current-count",
|
||||||
|
@ -132,33 +132,33 @@ var Constants = {
|
||||||
MaxMediaStorageUsageInMB: "x-ms-max-media-storage-usage-mb",
|
MaxMediaStorageUsageInMB: "x-ms-max-media-storage-usage-mb",
|
||||||
CurrentMediaStorageUsageInMB: "x-ms-media-storage-usage-mb",
|
CurrentMediaStorageUsageInMB: "x-ms-media-storage-usage-mb",
|
||||||
RequestCharge: "x-ms-request-charge",
|
RequestCharge: "x-ms-request-charge",
|
||||||
|
|
||||||
// Offer header
|
// Offer header
|
||||||
OfferType: "x-ms-offer-type",
|
OfferType: "x-ms-offer-type",
|
||||||
|
|
||||||
// Index progress headers
|
// Index progress headers
|
||||||
IndexTransformationProgress: "x-ms-documentdb-collection-index-transformation-progress",
|
IndexTransformationProgress: "x-ms-documentdb-collection-index-transformation-progress",
|
||||||
LazyIndexingProgress: "x-ms-documentdb-collection-lazy-indexing-progress",
|
LazyIndexingProgress: "x-ms-documentdb-collection-lazy-indexing-progress",
|
||||||
|
|
||||||
// Upsert header
|
// Upsert header
|
||||||
IsUpsert: "x-ms-documentdb-is-upsert"
|
IsUpsert: "x-ms-documentdb-is-upsert"
|
||||||
},
|
},
|
||||||
|
|
||||||
CurrentVersion: "2015-08-06",
|
CurrentVersion: "2015-08-06",
|
||||||
|
|
||||||
UserAgent: "documentdb-nodejs-sdk-1.5.5",
|
UserAgent: "documentdb-nodejs-sdk-1.5.6",
|
||||||
|
|
||||||
DefaultPrecisions: {
|
DefaultPrecisions: {
|
||||||
DefaultNumberHashPrecision: 3,
|
DefaultNumberHashPrecision: 3,
|
||||||
DefaultNumberRangePrecision: -1,
|
DefaultNumberRangePrecision: -1,
|
||||||
DefaultStringHashPrecision: 3,
|
DefaultStringHashPrecision: 3,
|
||||||
DefaultStringRangePrecision: -1
|
DefaultStringRangePrecision: -1
|
||||||
},
|
},
|
||||||
|
|
||||||
ConsistentHashRing: {
|
ConsistentHashRing: {
|
||||||
DefaultVirtualNodesPerCollection: 128
|
DefaultVirtualNodesPerCollection: 128
|
||||||
},
|
},
|
||||||
|
|
||||||
RegularExpressions: {
|
RegularExpressions: {
|
||||||
TrimLeftSlashes: new RegExp("^[/]+"),
|
TrimLeftSlashes: new RegExp("^[/]+"),
|
||||||
TrimRightSlashes: new RegExp("[/]+$")
|
TrimRightSlashes: new RegExp("[/]+$")
|
||||||
|
|
|
@ -33,7 +33,6 @@ var Range = Base.defineClass(
|
||||||
* @param {object} options - The Range constructor options.
|
* @param {object} options - The Range constructor options.
|
||||||
* @param {any} options.low - The low value in the range.
|
* @param {any} options.low - The low value in the range.
|
||||||
* @param {any} options.high - The high 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) {
|
function(options) {
|
||||||
if (options === undefined) {
|
if (options === undefined) {
|
||||||
|
@ -50,80 +49,11 @@ var Range = Base.defineClass(
|
||||||
}
|
}
|
||||||
this.low = options.low;
|
this.low = options.low;
|
||||||
this.high = options.high;
|
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);
|
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 */
|
/** @ignore */
|
||||||
_compare: function (x, y) {
|
_compare: function (x, y, compareFunction) {
|
||||||
// Same semantics as Array.sort
|
// Same semantics as Array.sort
|
||||||
// http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare
|
// http://www.ecma-international.org/ecma-262/6.0/#sec-sortcompare
|
||||||
if (x === undefined && y === undefined)
|
if (x === undefined && y === undefined)
|
||||||
|
@ -132,8 +62,8 @@ var Range = Base.defineClass(
|
||||||
return 1;
|
return 1;
|
||||||
if (y === undefined)
|
if (y === undefined)
|
||||||
return -1;
|
return -1;
|
||||||
if (this.compareFunction !== undefined) {
|
if (compareFunction !== undefined) {
|
||||||
var v = Number(this.compareFunction(x, y));
|
var v = Number(compareFunction(x, y));
|
||||||
if (v === NaN)
|
if (v === NaN)
|
||||||
return 0;
|
return 0;
|
||||||
return v;
|
return v;
|
||||||
|
@ -148,16 +78,39 @@ var Range = Base.defineClass(
|
||||||
},
|
},
|
||||||
|
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
_containsPoint: function (point) {
|
_contains: function (other, compareFunction) {
|
||||||
if (this._compare(point, this.low) >= 0 && this._compare(point, this.high) <= 0) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
_containsRange: function (other) {
|
_containsRange: function (other, compareFunction) {
|
||||||
if (this._compare(other.low, this.low) >= 0 && this._compare(other.high, this.high) <= 0) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -180,6 +133,11 @@ var Range = Base.defineClass(
|
||||||
this._state = this._states.ended;
|
this._state = this._states.ended;
|
||||||
callback(undefined, this.resources, this.resHeaders);
|
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.
|
* @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.
|
* 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 {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) {
|
if (partitionKeyExtractor === undefined || partitionKeyExtractor === null) {
|
||||||
throw new Error("partitionKeyExtractor cannot be null or undefined");
|
throw new Error("partitionKeyExtractor cannot be null or undefined");
|
||||||
}
|
}
|
||||||
|
@ -241,15 +200,20 @@ var RangePartitionResolver = Base.defineClass(
|
||||||
if (!allMapEntriesAreValid) {
|
if (!allMapEntriesAreValid) {
|
||||||
throw new Error("All partitionKeyMap entries have to be a tuple {range: Range, link: string }");
|
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.partitionKeyExtractor = partitionKeyExtractor;
|
||||||
this.partitionKeyMap = partitionKeyMap;
|
this.partitionKeyMap = partitionKeyMap;
|
||||||
|
this.compareFunction = compareFunction;
|
||||||
}, {
|
}, {
|
||||||
/**
|
/**
|
||||||
* Extracts the partition key from the specified document using the partitionKeyExtractor
|
* Extracts the partition key from the specified document using the partitionKeyExtractor
|
||||||
* @memberof RangePartitionResolver
|
* @memberof RangePartitionResolver
|
||||||
* @instance
|
* @instance
|
||||||
* @param {object} document - The document from which to extract the partition key.
|
* @param {object} document - The document from which to extract the partition key.
|
||||||
* @returns {}
|
* @returns {}
|
||||||
**/
|
**/
|
||||||
getPartitionKey: function (document) {
|
getPartitionKey: function (document) {
|
||||||
if (typeof this.partitionKeyExtractor === "string") {
|
if (typeof this.partitionKeyExtractor === "string") {
|
||||||
|
@ -260,7 +224,7 @@ var RangePartitionResolver = Base.defineClass(
|
||||||
}
|
}
|
||||||
throw new Error("Unable to extract partition key from document. Ensure PartitionKeyExtractor is a valid function or property name.");
|
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.
|
* Given a partition key, returns the correct collection link for creating a document using the range partition map.
|
||||||
* @memberof RangePartitionResolver
|
* @memberof RangePartitionResolver
|
||||||
|
@ -274,9 +238,9 @@ var RangePartitionResolver = Base.defineClass(
|
||||||
if (mapEntry !== undefined && mapEntry !== null) {
|
if (mapEntry !== undefined && mapEntry !== null) {
|
||||||
return mapEntry.link;
|
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.");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a partition key, returns a list of collection links to read from using the range partition map.
|
* Given a partition key, returns a list of collection links to read from using the range partition map.
|
||||||
* @memberof RangePartitionResolver
|
* @memberof RangePartitionResolver
|
||||||
|
@ -295,7 +259,8 @@ var RangePartitionResolver = Base.defineClass(
|
||||||
|
|
||||||
/** @ignore */
|
/** @ignore */
|
||||||
_getFirstContainingMapEntryOrNull: function (point) {
|
_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) {
|
if (containingMapEntries && containingMapEntries.length > 0) {
|
||||||
return containingMapEntries[0];
|
return containingMapEntries[0];
|
||||||
}
|
}
|
||||||
|
@ -306,10 +271,12 @@ var RangePartitionResolver = Base.defineClass(
|
||||||
_getIntersectingMapEntries: function (partitionKey) {
|
_getIntersectingMapEntries: function (partitionKey) {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
var partitionKeys = (partitionKey instanceof Array) ? partitionKey : [partitionKey];
|
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();
|
var result = new Array();
|
||||||
ranges.forEach(function (range) {
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"database",
|
"database",
|
||||||
"cloud"
|
"cloud"
|
||||||
],
|
],
|
||||||
"version": "1.5.5",
|
"version": "1.5.6",
|
||||||
"author": "Microsoft Corporation",
|
"author": "Microsoft Corporation",
|
||||||
"main": "./index.js",
|
"main": "./index.js",
|
||||||
"engine": {
|
"engine": {
|
||||||
|
|
|
@ -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 = "[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);
|
||||||
|
})
|
||||||
|
}</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>> 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";
|
"use strict";
|
||||||
|
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var ConsistentHashRing = require("../lib/Hash/consistentHashRing").ConsistentHashRing;
|
var ConsistentHashRing = require("../lib/hash/consistentHashRing").ConsistentHashRing;
|
||||||
|
|
||||||
describe("ConsistentHashRing new()", function () {
|
describe("ConsistentHashRing new()", function () {
|
||||||
it("valid arguments does not throw", 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";
|
"use strict";
|
||||||
|
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
var HashPartitionResolver = require("../lib/Hash/hashPartitionResolver").HashPartitionResolver;
|
var HashPartitionResolver = require("../lib/hash/hashPartitionResolver").HashPartitionResolver;
|
||||||
|
|
||||||
describe("HashPartitionResolver new()", function () {
|
describe("HashPartitionResolver new()", function () {
|
||||||
it(" does not throw", function () {
|
it(" does not throw", function () {
|
||||||
|
|
|
@ -23,7 +23,7 @@ SOFTWARE.
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var MurmurHash = require("../lib/Hash/murmurHash").MurmurHash;
|
var MurmurHash = require("../lib/hash/murmurHash").MurmurHash;
|
||||||
var assert = require("assert")
|
var assert = require("assert")
|
||||||
|
|
||||||
describe("MurmurHash.hash", function () {
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
Follow these instructions to run the tests locally.
|
Follow these instructions to run the tests locally.
|
||||||
|
|
||||||
##Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
1. Clone Azure/azure-documentdb-node repository
|
1. Clone Azure/azure-documentdb-node repository
|
||||||
Please clone the source and tests from [https://github.com/Azure/azure-documentdb-node](https://github.com/Azure/azure-documentdb-node)
|
Please clone the source and tests from [https://github.com/Azure/azure-documentdb-node](https://github.com/Azure/azure-documentdb-node)
|
||||||
|
@ -11,7 +11,7 @@ Please clone the source and tests from [https://github.com/Azure/azure-documentd
|
||||||
3. Install mocha package globally
|
3. Install mocha package globally
|
||||||
> npm install -g mocha
|
> npm install -g mocha
|
||||||
|
|
||||||
##Running the tests
|
## Running the tests
|
||||||
Using your command-line tool, from the root of your local copy of azure-documentdb-node repository:
|
Using your command-line tool, from the root of your local copy of azure-documentdb-node repository:
|
||||||
If you are contributing changes and submitting PR then you need to ensure that you run the tests against your local copy of the source, and not the published npm package.
|
If you are contributing changes and submitting PR then you need to ensure that you run the tests against your local copy of the source, and not the published npm package.
|
||||||
|
|
||||||
|
|
|
@ -23,16 +23,18 @@ SOFTWARE.
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Base = require("documentdb").Base
|
var lib = require("../lib/"),
|
||||||
, DocumentDBClient = require("documentdb").DocumentClient
|
assert = require("assert"),
|
||||||
, DocumentBase = require("documentdb").DocumentBase
|
testConfig = require("./_testConfig"),
|
||||||
, Constants = require("documentdb").Constants
|
Stream = require("stream");
|
||||||
, assert = require("assert")
|
|
||||||
, testConfig = require("./_testConfig")
|
var Base = lib.Base,
|
||||||
, Stream = require("stream")
|
DocumentDBClient = lib.DocumentClient,
|
||||||
, Range = require("documentdb").Range
|
DocumentBase = lib.DocumentBase,
|
||||||
, RangePartitionResolver = require("documentdb").RangePartitionResolver
|
Constants = lib.Constants,
|
||||||
, HashPartitionResolver = require("documentdb").HashPartitionResolver;
|
Range = lib.Range,
|
||||||
|
RangePartitionResolver = lib.RangePartitionResolver,
|
||||||
|
HashPartitionResolver = lib.HashPartitionResolver;
|
||||||
|
|
||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||||
|
|
||||||
|
@ -2285,951 +2287,7 @@ describe("NodeJS CRUD Tests", function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("setIsUpsertHeader Unit Tests", function () {
|
describe("HashPartitionResolver", 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 () {
|
|
||||||
|
|
||||||
var test = function (useUpsert, done) {
|
var test = function (useUpsert, done) {
|
||||||
var client = new DocumentDBClient(host, { masterKey: masterKey });
|
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("CRUD operations", 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 with upsert", function (done) { test(true, done) });
|
||||||
});
|
});
|
||||||
});
|
});
|
Загрузка…
Ссылка в новой задаче