You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by iv...@apache.org on 2015/07/13 17:43:17 UTC

incubator-ignite git commit: #ignite-961-promise: wip

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-961-promise 9ccabbaa4 -> dace2ecb3


#ignite-961-promise: wip


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/dace2ecb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/dace2ecb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/dace2ecb

Branch: refs/heads/ignite-961-promise
Commit: dace2ecb30e098369a8c080c52f3c4b0bda3647e
Parents: 9ccabba
Author: ivasilinets <iv...@gridgain.com>
Authored: Mon Jul 13 18:43:11 2015 +0300
Committer: ivasilinets <iv...@gridgain.com>
Committed: Mon Jul 13 18:43:11 2015 +0300

----------------------------------------------------------------------
 modules/nodejs/src/main/js/apache-ignite.js     |   1 +
 modules/nodejs/src/main/js/ignite.js            |   2 -
 modules/nodejs/src/main/js/ignition-promise.js  | 111 ++++
 modules/nodejs/src/main/js/server-promises.js   | 253 +++++++++
 .../ScriptingJsCachePromisesApiSelfTest.java    | 227 ++++++++
 .../src/test/js/test-cache-promise-api.js       | 562 +++++++++++++++++++
 modules/nodejs/src/test/js/test-utils.js        |  10 +
 7 files changed, 1164 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/main/js/apache-ignite.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/apache-ignite.js b/modules/nodejs/src/main/js/apache-ignite.js
index 053b88a..d670e32 100644
--- a/modules/nodejs/src/main/js/apache-ignite.js
+++ b/modules/nodejs/src/main/js/apache-ignite.js
@@ -16,6 +16,7 @@
  */
 
 module.exports = {
+    IgnitionPromise : require('./ignition-promise.js').IgnitionPromise,
     Cache : require('./cache.js').Cache,
     CacheEntry : require('./cache.js').CacheEntry,
     Ignition : require('./ignition.js').Ignition,

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/main/js/ignite.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/ignite.js b/modules/nodejs/src/main/js/ignite.js
index edc0301..71d6e3e 100644
--- a/modules/nodejs/src/main/js/ignite.js
+++ b/modules/nodejs/src/main/js/ignite.js
@@ -63,7 +63,6 @@ Ignite.prototype.cachePromise = function(cacheName) {
     return new CachePromise(this._server, cacheName);
 }
 
-
 /**
  * Get or create an instance of cache
  *
@@ -86,7 +85,6 @@ Ignite.prototype.getOrCreateCache = function(cacheName, callback) {
         onCreateCallback.bind(this, callback));
 }
 
-
 /**
  * Get or create an instance of cache
  *

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/main/js/ignition-promise.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/ignition-promise.js b/modules/nodejs/src/main/js/ignition-promise.js
new file mode 100644
index 0000000..4aa6035
--- /dev/null
+++ b/modules/nodejs/src/main/js/ignition-promise.js
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Creates an instance of Ignition
+ *
+ * @constructor
+ */
+function IgnitionPromise() {
+}
+
+/**
+ * Callback for Ignition start
+ *
+ * @callback Ignition~onStart
+ * @param {string} error Error
+ * @param {Ignite} ignite Connected ignite
+ */
+
+/**
+ * Open connection with ignite node
+ *
+ * @param {string[]} address List of nodes hosts with ports
+ * @param {string} secretKey Secret key.
+ */
+IgnitionPromise.start = function(address, secretKey) {
+    return new Promise(function(resolve, reject) {
+        var Server = require("./server").Server;
+        var Ignite = require("./ignite").Ignite
+
+        var numConn = 0;
+
+        for (var addr of address) {
+            var params = addr.split(":");
+
+            var portsRange = params[1].split("..");
+
+            var start;
+            var end;
+
+            if (portsRange.length === 1) {
+                start = parseInt(portsRange[0], 10);
+                end = start;
+            }
+            else if (portsRange.length === 2) {
+                start = parseInt(portsRange[0], 10);
+                end = parseInt(portsRange[1], 10);
+            }
+
+            if (isNaN(start) || isNaN(end)) {
+                incorrectAddress();
+
+                return;
+            }
+
+            for (var i = start; i <= end; i++) {
+                checkServer(params[0], i, secretKey);
+            }
+        }
+
+        function checkServer(host, port, secretKey) {
+            numConn++;
+
+            var server = new Server(host, port, secretKey);
+
+            server.checkConnection(onConnect.bind(null, server));
+        }
+
+        var needVal = true;
+
+        function incorrectAddress() {
+            reject("Incorrect address format.");
+
+            needVal = false;
+        }
+
+        function onConnect(server, error) {
+            if (!needVal) return;
+
+            numConn--;
+
+            if (!error) {
+                resolve(new Ignite(server));
+
+                needVal = false;
+
+                return;
+            }
+
+            if (!numConn) {
+                reject("Cannot connect to servers. " + error);
+            }
+        }
+    });
+}
+
+exports.IgnitionPromise = IgnitionPromise;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/main/js/server-promises.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/server-promises.js b/modules/nodejs/src/main/js/server-promises.js
new file mode 100644
index 0000000..40a5dd3
--- /dev/null
+++ b/modules/nodejs/src/main/js/server-promises.js
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Creates an instance of Server
+ *
+ * @constructor
+ * @this {Server}
+ * @param {string} host Host address
+ * @param {number} port Port
+ * @param {string} secretKey Secret key for connection
+ */
+function Server(host, port, secretKey) {
+    this._host = host;
+    this._port = port;
+    this._secretKey = secretKey;
+}
+
+/**
+ * Host value
+ *
+ * @this {Server}
+ * @returns {string} Host value
+ */
+Server.prototype.host = function() {
+    return this._host;
+}
+
+/**
+ * Callback for Server runCommand
+ *
+ * @callback onGet
+ * @param {string} error Error
+ * @param {string} result Result value
+ */
+
+/**
+ * @callback noValue
+ * @param {string} error Error
+ */
+
+/**
+ * Run http request
+ *
+ * @this {Server}
+ * @param {Command} cmd Command
+ */
+Server.prototype.runCommand = function(cmd) {
+    return new Promise(function(resolve, reject) {
+        var requestQry = "cmd=" + cmd.name() + cmd.paramsString();
+
+        var http = require('http');
+
+        var options = {
+            host: this._host,
+            port: this._port,
+            method : cmd._method(),
+            path: "/ignite?" + requestQry,
+            headers: this._signature()
+        };
+
+        if (cmd._isPost()) {
+            options.headers['Content-Length'] = cmd.postData().length;
+            options.headers['JSONObject'] = "true";
+        }
+
+        function streamCallback(response) {
+            var fullResponseString = '';
+
+            response.on('data', function (chunk) {
+                fullResponseString += chunk;
+            });
+
+            response.on('end', function () {
+                if (response.statusCode !== 200) {
+                    if (response.statusCode === 401) {
+                        reject("Authentication failed. Status code 401.");
+                    }
+                    else {
+                        reject("Request failed. Status code " + response.statusCode);
+                    }
+
+                    return;
+                }
+
+                var igniteResponse;
+
+                try {
+                    igniteResponse = JSON.parse(fullResponseString);
+                }
+                catch (e) {
+                    reject(e);
+
+                    return;
+                }
+
+                if (igniteResponse.successStatus) {
+                    reject(igniteResponse.error)
+                }
+                else {
+                    resolve(igniteResponse.response);
+                }
+            });
+        }
+
+        var request = http.request(options, streamCallback);
+
+
+        request.setTimeout(20000, function() {reject("Request timeout: >5 sec")});
+
+        request.on('error', function(err) {reject(err)});
+
+        if (cmd._isPost()) {
+            request.write(cmd.postData());
+        }
+
+        request.end();
+    });
+}
+
+/**
+ * Check the connection with server node.
+ *
+ * @this {Server}
+ * @param {onGet} callback Called on finish
+ */
+Server.prototype.checkConnection = function(callback) {
+    this.runCommand(new Command("version"), callback);
+}
+
+/**
+ * Get signature for connection.
+ *
+ * @this {Server}
+ * @returns Signature
+ */
+Server.prototype._signature = function() {
+    if (!this._secretKey) {
+        return {};
+    }
+
+    var loadTimeInMS = Date.now();
+
+    var baseKey = '' + loadTimeInMS + ":" + this._secretKey;
+
+    var crypto = require('crypto')
+
+    var shasum = crypto.createHash('sha1');
+
+    shasum.update(baseKey, 'binary');
+
+    var hash = shasum.digest('base64');
+
+    var key = loadTimeInMS + ":" + hash;
+
+    return {"X-Signature" : key};
+}
+
+/**
+ * @param {noValue} f Function
+ * @returns {string} Encoding function
+ */
+Server._escape = function(f) {
+    var qs = require('querystring');
+
+    return qs.escape(f.toString());
+}
+
+/**
+ * @constructor
+ * @this{Command}
+ * @param{string} name Command name.
+ */
+function Command(name) {
+    this._name = name;
+    this._params = [];
+}
+
+/**
+ * @this {Command}
+ * @param {string} key Key
+ * @param {string} val Value
+ * @returns this
+ */
+Command.prototype.addParam = function(key, value) {
+    this._params.push({key: key, value: value});
+    return this;
+}
+
+/**
+ * @this {Command}
+ * @param{JSONObject} postData Post data.
+ * @returns this
+ */
+Command.prototype.setPostData = function(postData) {
+    this._postData = postData;
+    return this;
+}
+
+/**
+ * @this {Command}
+ * @returns Post data.
+ */
+Command.prototype.postData = function() {
+    return this._postData;
+}
+
+/**
+ * @this {Command}
+ * @returns Command name.
+ */
+Command.prototype.name = function() {
+    return this._name;
+}
+
+/**
+ * @this {Command}
+ * @returns Http request string.
+ */
+Command.prototype.paramsString = function() {
+    var paramsString = "";
+
+    for (var p of this._params) {
+        paramsString += "&" + Server._escape(p.key) + "=" + Server._escape(p.value);
+    }
+
+    return paramsString;
+}
+
+Command.prototype._method = function() {
+    return this._isPost()? "POST" : "GET";
+}
+
+Command.prototype._isPost = function() {
+    return !!this._postData;
+}
+
+exports.Server = Server;
+exports.Command = Command;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/test/java/org/apache/ignite/internal/ScriptingJsCachePromisesApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/java/org/apache/ignite/internal/ScriptingJsCachePromisesApiSelfTest.java b/modules/nodejs/src/test/java/org/apache/ignite/internal/ScriptingJsCachePromisesApiSelfTest.java
new file mode 100644
index 0000000..02cce7b
--- /dev/null
+++ b/modules/nodejs/src/test/java/org/apache/ignite/internal/ScriptingJsCachePromisesApiSelfTest.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal;
+
+/**
+ * Test node js client put/get.
+ */
+public class ScriptingJsCachePromisesApiSelfTest extends NodeJsAbstractTest {
+    /**
+     * Constructor.
+     */
+    public ScriptingJsCachePromisesApiSelfTest() {
+        super("test-cache-promise-api.js");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        startGrid(0);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        grid(0).cache(NodeJsAbstractTest.CACHE_NAME).removeAll();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutGet() throws Exception {
+        runJsScript("testPutGet");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutGetObject() throws Exception {
+        runJsScript("testPutGetObject");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testIncorrectCache() throws Exception {
+        runJsScript("testIncorrectCacheName");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetOrCreateCacheName() throws Exception {
+        runJsScript("testGetOrCreateCacheName");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemove() throws Exception {
+        runJsScript("testRemove");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveNoKey() throws Exception {
+        runJsScript("testRemoveNoKey");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAll() throws Exception {
+        runJsScript("testRemoveAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAllGetAll() throws Exception {
+        runJsScript("testPutAllGetAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutAllObjectGetAll() throws Exception {
+        runJsScript("testPutAllObjectGetAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAllObjectGetAll() throws Exception {
+        runJsScript("testRemoveAllObjectGetAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testContains() throws Exception {
+        runJsScript("testContains");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutContains() throws Exception {
+        runJsScript("testPutContains");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutContainsAll() throws Exception {
+        runJsScript("testPutContainsAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNotContainsAll() throws Exception {
+        runJsScript("testNotContainsAll");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAndPut() throws Exception {
+        runJsScript("testGetAndPut");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAndPutIfAbsent() throws Exception {
+        runJsScript("testGetAndPutIfAbsent");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testPutIfAbsent() throws Exception {
+        runJsScript("testPutIfAbsent");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAndRemove() throws Exception {
+        runJsScript("testGetAndRemove");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveValue() throws Exception {
+        runJsScript("testRemoveValue");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoveAllFromCache() throws Exception {
+        runJsScript("testRemoveAllFromCache");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReplace() throws Exception {
+        runJsScript("testReplace");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testIncorrectReplaceObject() throws Exception {
+        runJsScript("testIncorrectReplaceObject");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReplaceObject() throws Exception {
+        runJsScript("testReplaceObject");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetAndReplaceObject() throws Exception {
+        runJsScript("testGetAndReplaceObject");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReplaceValueObject() throws Exception {
+        runJsScript("testReplaceValueObject");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSize() throws Exception {
+        runJsScript("testSize");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/test/js/test-cache-promise-api.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/js/test-cache-promise-api.js b/modules/nodejs/src/test/js/test-cache-promise-api.js
new file mode 100644
index 0000000..efb7107
--- /dev/null
+++ b/modules/nodejs/src/test/js/test-cache-promise-api.js
@@ -0,0 +1,562 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var TestUtils = require("./test-utils").TestUtils;
+
+var Ignite = require(TestUtils.scriptPath());
+var CacheEntry = Ignite.CacheEntry;
+
+var assert = require("assert");
+
+testPutGet = function() {
+    var key = "key";
+    var val = "6";
+
+    TestUtils.startIgnitePromiseNode().then(function(ignite) {
+        var cache = ignite.cachePromise("mycache");
+        cache.put(key, val).then(function() {
+            return cache.get(key);
+        }).then(function(res) {
+            console.log("GET" + res);
+            assert(TestUtils.compareObject(val, res), "Get incorrect value on get [exp=" +
+                JSON.stringify(val) + ", val=" + JSON.stringify(res) + "]");
+            TestUtils.testDone();
+        }).catch(function (err) {
+            assert(err === null, err);
+        })
+    }).catch(function (err) {
+        assert(err === null, err);
+    });
+}
+
+testPutGetObject = function() {
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    TestUtils.startIgnitePromiseNode().then(function(ignite) {
+        var cache = ignite.cachePromise("mycache");
+
+        cache.put(key, val).then(function() {
+            return cache.get(key);
+        }).then(function(res) {
+            assert(TestUtils.compareObject(val, res), "Get incorrect value on get [exp=" +
+                JSON.stringify(val) + ", val=" + JSON.stringify(res) + "]");
+            TestUtils.testDone();
+        })
+    });
+}
+
+testPutContains = function() {
+    var key = "key";
+    var val = "6";
+
+    TestUtils.startIgnitePromiseNode().then(function(ignite) {
+        var cache = ignite.cachePromise("mycache");
+
+        cache.put(key, val).then(function() {
+            return cache.contains(key);
+        }).then(function(res) {
+            assert(val === true, "Incorrect result [expected=" + true + ", val=" + res + "]");
+
+            TestUtils.testDone();
+        }).catch(function (err) {
+            assert(err === null, err);
+        })
+    });
+}
+
+testContains = function() {
+    var key = "key";
+
+    TestUtils.startIgnitePromiseNode().then(function(ignite) {
+        var cache = ignite.cachePromise("mycache");
+
+        cache.contains(key).then(function(res) {
+            assert(val === true, "Incorrect result [expected=" + true + ", val=" + res + "]");
+
+            TestUtils.testDone();
+        }).catch(function (err) {
+            assert(err === null, err);
+        })
+    });
+}
+
+testPutContainsAll = function() {
+    startTest(false, "mycache", {trace: [putAll, containsKeys], entry: objectEntries()});
+}
+
+testNotContainsAll = function() {
+    startTest(false, "mycache", {trace: [notContainsKeys], entry: stringEntries()});
+}
+
+testRemove = function() {
+    startTest(false, "mycache", {trace: [put, getExist, remove, getNonExist], entry: ["key" , "6"]});
+}
+
+testRemoveNoKey = function() {
+    startTest(false, "mycache", {trace: [remove, getNonExist], entry: ["key" , "6"]});
+}
+
+testPutAllGetAll = function() {
+    startTest(false, "mycache", {trace: [putAll, getAll], entry: stringEntries()});
+}
+
+testPutAllObjectGetAll = function() {
+    startTest(false, "mycache", {trace: [putAll, getAll], entry: objectEntries()});
+}
+
+testRemoveAllObjectGetAll = function() {
+    startTest(false, "mycache", {trace: [putAll, getAll, removeAll, getNone], entry: objectEntries()});
+}
+
+testRemoveAll = function() {
+    startTest(false, "mycache", {trace: [putAll, getAll, removeAll, getNone], entry: stringEntries()});
+}
+
+testIncorrectCacheName = function() {
+    startTest(false, "mycache1", {trace: [incorrectPut], entry: ["key", "6"]});
+}
+
+testGetOrCreateCacheName = function() {
+    startTest(true, "mycache2", {trace: [put, getExist], entry: ["key", "6"]});
+}
+
+testGetAndPut = function() {
+    function onGetAndPut(err, res) {
+        assert(err === null, "Get error on get and put [err=" + err + "]");
+        assert(res === "6", "Incorrect result for getAndPut [expected=6, val" + res + "]");
+
+        TestUtils.testDone();
+    }
+
+    function getAndPut(cache, entry, next) {
+        cache.getAndPut("key", "7", onGetAndPut);
+    }
+
+    startTest(false, "mycache", {trace: [put, getAndPut], entry: ["key", "6"]});
+}
+
+testGetAndPutIfAbsent = function() {
+    function getAndPutIfAbsent(cache, entry, next) {
+        cache.getAndPutIfAbsent("key", "7", onGetAndPutIfAbsent);
+
+        function onGetAndPutIfAbsent(err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === "6", "Incorrect result for getAndPutIfAbsent [expected=6, val" + res + "]");
+
+            next();
+        }
+    }
+
+    startTest(false, "mycache", {trace: [put, getAndPutIfAbsent, getExist], entry: ["key", "6"]});
+}
+
+testPutIfAbsent = function() {
+    function putIfAbsent(cache, entry, next) {
+        cache.putIfAbsent("key", "7", onPutIfAbsent);
+
+        function onPutIfAbsent(err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === false, "Incorrect result for putIfAbsent [expected=false, val" + res + "]");
+
+            next();
+        }
+    }
+
+    startTest(false, "mycache", {trace: [put, putIfAbsent, getExist], entry: ["key", "6"]});
+}
+
+testRemoveValue = function() {
+    function removeValue(cache, entry, next) {
+        cache.removeValue("key", "7", onRemoveValue);
+
+        function onRemoveValue(err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === false, "Incorrect result for onRemoveValue [expected=false, val" + res + "]");
+
+            next();
+        }
+    }
+
+    startTest(false, "mycache", {trace: [put, removeValue, getExist], entry: ["key", "6"]});
+}
+
+testGetAndRemove = function() {
+    function getAndRemove(cache, entry, next) {
+        cache.getAndRemove("key", onGetAndRemove);
+
+        function onGetAndRemove(err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === "6", "Incorrect result for getAndPut [expected=6, val" + res + "]");
+
+            next();
+        }
+    }
+
+    startTest(false, "mycache", {trace: [put, getAndRemove, getNone], entry: ["key", "6"]});
+}
+
+testRemoveAllFromCache = function() {
+    function removeAllFromCache(cache, entry, next) {
+        cache.removeAllFromCache(next);
+    }
+
+    startTest(false, "mycache", {trace: [put, removeAllFromCache, getNone], entry: ["key", "6"]});
+}
+
+testReplace = function() {
+    function replace(cache, entry, next) {
+        cache.replace(entry[0], "7", onReplace.bind(null, cache));
+
+        function onReplace(cache, err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === true, "Incorrect result for replace [expected=true, val=" + res + "]");
+
+            cache.get(entry[0], function(err, res) {
+                assert(!err);
+                assert("7" === res, "Get incorrect value on get [exp=7, val=" + res + "]");
+                next();
+            });
+        }
+    }
+
+    startTest(false, "mycache", {trace: [put, replace], entry: ["key", "6"]});
+}
+
+testReplaceObject = function() {
+    function replace(cache, entry, next) {
+        var newKey = {"key" :"7"};
+        cache.replace(entry[0], newKey, onReplace.bind(null, cache));
+
+        function onReplace(cache, err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === true, "Incorrect result for replace [expected=true, val" + res + "]");
+
+            cache.get(entry[0], function(err, res) {
+                assert(!err);
+                assert(TestUtils.compareObject(newKey, res), "Get incorrect value on get.");
+
+                next();
+            });
+        }
+    }
+
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    startTest(false, "mycache", {trace: [put, replace], entry: [key, val]});
+}
+
+testGetAndReplaceObject = function() {
+    function getAndReplace(cache, entry, next) {
+        var newKey = {"key" :"7"};
+        cache.getAndReplace(entry[0], newKey, onGetAndReplace.bind(null, cache));
+
+        function onGetAndReplace(cache, err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(TestUtils.compareObject(val, res), "Get incorrect value on get.");
+
+            next();
+        }
+    }
+
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    startTest(false, "mycache", {trace: [put, getAndReplace], entry: [key, val]});
+}
+
+testReplaceValueObject = function() {
+    function replaceValue(cache, entry, next) {
+        var newVal = {"key" :"7"};
+        cache.replaceValue(entry[0], newVal, entry[1], onReplaceValue.bind(null, cache));
+
+        function onReplaceValue(cache, err, res) {
+            assert(err === null, "Get error on get and put [err=" + err + "]");
+            assert(res === true, "Incorrect result for replace [expected=true, val" + res + "]");
+            next();
+        }
+    }
+
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    startTest(false, "mycache", {trace: [put, replaceValue], entry: [key, val]});
+}
+
+testIncorrectReplaceObject = function() {
+    function replace(cache, entry, next) {
+        cache.replace(entry[0], "7", onReplace.bind(null, cache));
+
+        function onReplace(cache, err, res) {
+            assert(err !== null, "Do not get error");
+            assert(err.indexOf("Failed to update keys") > -1, "Incorrect error message: " + err);
+            next();
+        }
+    }
+
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    startTest(false, "mycache", {trace: [put, replace], entry: [key, val]});
+}
+
+testSize = function() {
+    function onSize(exp, next, cache, err, res) {
+            assert(err === null, "Do not get error");
+            assert(res === exp, "Incorrect size: " + res);
+
+            next();
+    }
+
+    function size0(cache, entry, next) {
+        cache.size(onSize.bind(null, 0, next, cache));
+    }
+
+    function size1(cache, entry, next) {
+        cache.size(onSize.bind(null, 1, next, cache));
+    }
+
+    var key = {"name" : "Paul"};
+    var val = {"age" : 12, "books" : ["1", "Book"]};
+
+    startTest(false, "mycache", {trace: [size0, put, size1], entry: [key, val]});
+}
+
+function objectEntries() {
+    entries = [];
+
+    var key1 = {"name" : "Ann"};
+    var key2 = {"name" : "Paul"};
+    var val1 = {"age" : 12, "books" : ["1", "Book"]};
+    var val2 = {"age" : 13, "books" : ["1", "Book"]};
+
+    entries.push(new CacheEntry(key1, val1));
+    entries.push(new CacheEntry(key2, val2));
+
+    return entries;
+}
+
+function stringEntries() {
+    entries = [];
+
+    entries.push(new CacheEntry("key1", "val1"));
+    entries.push(new CacheEntry("key2", "val2"));
+
+    return entries;
+}
+
+function startTest(createCache, cacheName, testDescription) {
+    TestUtils.startIgniteNode(onStart.bind(null, createCache, cacheName, testDescription));
+}
+
+function onStart(createCache, cacheName, testDescription, error, ignite) {
+    if (createCache) {
+        ignite.getOrCreateCache(cacheName, function(err, cache) {
+            assert(err === null, err);
+
+            function callNext(error) {
+                assert(!error);
+                var next = testDescription.trace.shift();
+                if (next)
+                    next.call(null, cache, testDescription.entry, callNext);
+                else
+                    TestUtils.testDone();
+            }
+
+            callNext();
+        });
+    }
+    else {
+        var cache = ignite.cache(cacheName);
+
+        function callNext(error) {
+            assert(!error);
+            var next = testDescription.trace.shift();
+            if (next)
+                next.call(null, cache, testDescription.entry, callNext);
+            else
+                TestUtils.testDone();
+        }
+
+        callNext();
+    }
+
+
+}
+
+function put(cache, entry, next) {
+    cache.put(entry[0], entry[1], next);
+}
+
+function containsKey(cache, entry, next) {
+    cache.containsKey(entry[0], onContainsKey);
+
+    function onContainsKey(err, val) {
+        assert(err === null, "Error on contains key [err=" + err + "]");
+        assert(val === true, "Incorrect result [expected=" + true + ", val=" + val + "]");
+
+        TestUtils.testDone();
+    }
+}
+
+function notContainsKey(cache, entry, next) {
+    cache.containsKey(entry[0], onContainsKey);
+
+    function onContainsKey(err, val) {
+        assert(err === null, "Error on contains key [err=" + err + "]");
+        assert(val === false, "Incorrect result [expected=" + false + ", val=" + val + "]");
+
+        TestUtils.testDone();
+    }
+}
+
+function containsKeys(cache, entries, next) {
+    var keys = []
+
+    for (var entry of entries) {
+        keys.push(entry.key);
+    }
+
+    cache.containsKeys(keys, onContainsKeys);
+
+    function onContainsKeys(err, val) {
+        assert(err === null, "Error on contains key [err=" + err + "]");
+        assert(val === true, "Incorrect result [expected=" + true + ", val=" + val + "]");
+
+        TestUtils.testDone();
+    }
+}
+
+function notContainsKeys(cache, entries, next) {
+    var keys = []
+
+    for (var entry of entries) {
+        keys.push(entry.key);
+    }
+
+    cache.containsKeys(keys, onContainsKeys);
+
+    function onContainsKeys(err, val) {
+        assert(err === null, "Error on contains key [err=" + err + "]");
+        assert(val === false, "Incorrect result [expected=" + false + ", val=" + val + "]");
+
+        TestUtils.testDone();
+    }
+}
+
+function getExist(cache, entry, next) {
+    function onGet(error, value) {
+        assert(!error);
+        assert(TestUtils.compareObject(entry[1], value), "Get incorrect value on get [exp=" +
+            JSON.stringify(entry[1]) + ", val=" + JSON.stringify(value) + "]");
+        next();
+    }
+
+    cache.get(entry[0], onGet);
+}
+
+function remove(cache, entry, next) {
+    cache.remove(entry[0], next);
+}
+
+function getNonExist(cache, entry, next) {
+    cache.get(entry[0], onGet);
+
+    function onGet(error, value) {
+        assert(!error);
+        assert(!value);
+        next();
+    }
+}
+
+function putAll(cache, entries, next) {
+    cache.putAll(entries, next);
+}
+
+function getAll(cache, entries, next) {
+    var keys = []
+
+    for (var entry of entries) {
+        keys.push(entry.key);
+    }
+
+    cache.getAll(keys, onGetAll.bind(null, keys));
+
+    var expected = entries;
+
+    function onGetAll(keys, error, values) {
+        assert(!error, error);
+
+        assert(values.length === keys.length, "Values length is incorrect "
+            + "[expected=" + keys.length + ", real=" + values.length + "]");
+
+        for (var i = 0; i < keys.length; ++i) {
+            var key = keys[i];
+
+            var foundVal = null;
+
+            for (var j = 0; j < values.length; ++j) {
+                if (TestUtils.compareObject(key, values[j].key)) {
+                    foundVal = values[j];
+                }
+            }
+
+            var foundExp = null;
+
+            for (var j = 0; j < expected.length; ++j) {
+                if (TestUtils.compareObject(key, expected[j].key)) {
+                    foundExp = expected[j];
+                }
+            }
+
+            assert(foundVal !== null, "Cannot find key. [key=" + key + "].");
+            assert(foundExp !== null, "Cannot find key. [key=" + key + "].");
+
+            assert(TestUtils.compareObject(foundExp, foundVal), "Incorrect value");
+        }
+
+        next();
+    }
+}
+
+function removeAll(cache, entries, next) {
+    cache.removeAll(Object.keys(entries), next)
+}
+
+function getNone(cache, entries, next) {
+    cache.getAll(Object.keys(entries), onGetAll);
+
+    function onGetAll(error, values) {
+        assert(!error, error);
+        assert(!values || !Object.keys(values).length);
+
+        next();
+    }
+}
+
+function incorrectPut(cache, entry, next) {
+    cache.put(entry[0], entry[1], callback);
+
+    function callback(error) {
+        assert(!!error, "Do not get error for not exist cache");
+        assert(error.indexOf("Failed to find cache for given cache name") !== -1,
+            "Incorrect message on not exist cache. " + error);
+
+        next();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/dace2ecb/modules/nodejs/src/test/js/test-utils.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/js/test-utils.js b/modules/nodejs/src/test/js/test-utils.js
index 8beb3dc..a90cd0a 100644
--- a/modules/nodejs/src/test/js/test-utils.js
+++ b/modules/nodejs/src/test/js/test-utils.js
@@ -161,6 +161,16 @@ TestUtils.startIgniteNode = function(callback) {
 
 /**
  * Starts ignite node with default config
+ */
+TestUtils.startIgnitePromiseNode = function() {
+    var Ignite = require(TestUtils.scriptPath());
+    var IgnitionPromise = Ignite.IgnitionPromise;
+
+    return IgnitionPromise.start(['127.0.0.1:9095'], null);
+}
+
+/**
+ * Starts ignite node with default config
  *
  * @param {string} secretKey Secret key
  * @param {Ignition~onStart} callback Called on connect