Commit 2f0d6985 authored by chrisgao@chromium.org's avatar chrisgao@chromium.org

[chromedriver] Fix issue of cache id in JS.

Also enable three passed java tests.

NOTRY=true

Review URL: https://chromiumcodereview.appspot.com/14230010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194743 0039d316-1c4b-4281-b951-d872f2087c98
parent 0f1320ae
...@@ -35,6 +35,7 @@ var ELEMENT_KEY = 'ELEMENT'; ...@@ -35,6 +35,7 @@ var ELEMENT_KEY = 'ELEMENT';
function Cache() { function Cache() {
this.cache_ = {}; this.cache_ = {};
this.nextId_ = 1; this.nextId_ = 1;
this.idPrefix_ = Math.random().toString();
} }
Cache.prototype = { Cache.prototype = {
...@@ -45,12 +46,12 @@ Cache.prototype = { ...@@ -45,12 +46,12 @@ Cache.prototype = {
* @param {!Object} item The item to store in the cache. * @param {!Object} item The item to store in the cache.
* @return {number} The ID for the cached item. * @return {number} The ID for the cached item.
*/ */
storeItem_: function(item) { storeItem: function(item) {
for (var i in this.cache_) { for (var i in this.cache_) {
if (item == this.cache_[i]) if (item == this.cache_[i])
return i; return i;
} }
var id = this.nextId_.toString(); var id = this.idPrefix_ + ':' + this.nextId_;
this.cache_[id] = item; this.cache_[id] = item;
this.nextId_++; this.nextId_++;
return id; return id;
...@@ -62,7 +63,7 @@ Cache.prototype = { ...@@ -62,7 +63,7 @@ Cache.prototype = {
* @param {number} id The ID for the cached item to retrieve. * @param {number} id The ID for the cached item to retrieve.
* @return {!Object} The retrieved item. * @return {!Object} The retrieved item.
*/ */
retrieveItem_: function(id) { retrieveItem: function(id) {
var item = this.cache_[id]; var item = this.cache_[id];
if (item) if (item)
return item; return item;
...@@ -86,63 +87,67 @@ Cache.prototype = { ...@@ -86,63 +87,67 @@ Cache.prototype = {
if (!node) if (!node)
delete this.cache_[id]; delete this.cache_[id];
} }
}, }
};
/** /**
* Returns the global object cache for the page.
* @param {Document=} opt_doc The document whose cache to retrieve. Defaults to
* the current document.
* @return {!Cache} The page's object cache.
*/
function getPageCache(opt_doc) {
var doc = opt_doc || document;
// We use the same key as selenium's javascript/atoms/inject.js.
var key = '$wdc_';
if (!(key in doc))
doc[key] = new Cache();
return doc[key];
}
/**
* Wraps the given value to be transmitted remotely by converting * Wraps the given value to be transmitted remotely by converting
* appropriate objects to cached object IDs. * appropriate objects to cached object IDs.
* *
* @param {*} value The value to wrap. * @param {*} value The value to wrap.
* @return {*} The wrapped value. * @return {*} The wrapped value.
*/ */
wrap: function(value) { function wrap(value) {
if (typeof(value) == 'object' && value != null) { if (typeof(value) == 'object' && value != null) {
var nodeType = value['nodeType']; var nodeType = value['nodeType'];
if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT) { if (nodeType == NodeType.ELEMENT || nodeType == NodeType.DOCUMENT) {
var wrapped = {}; var wrapped = {};
wrapped[ELEMENT_KEY] = this.storeItem_(value); wrapped[ELEMENT_KEY] = getPageCache(value.ownerDocument).storeItem(value);
return wrapped; return wrapped;
} }
var obj = (typeof(value.length) == 'number') ? [] : {}; var obj = (typeof(value.length) == 'number') ? [] : {};
for (var prop in value) for (var prop in value)
obj[prop] = this.wrap(value[prop]); obj[prop] = wrap(value[prop]);
return obj; return obj;
} }
return value; return value;
}, }
/** /**
* Unwraps the given value by converting from object IDs to the cached * Unwraps the given value by converting from object IDs to the cached
* objects. * objects.
* *
* @param {*} value The value to unwrap. * @param {*} value The value to unwrap.
* @param {Cache} cache The cache to retrieve wrapped elements from.
* @return {*} The unwrapped value. * @return {*} The unwrapped value.
*/ */
unwrap: function(value) { function unwrap(value, cache) {
if (typeof(value) == 'object' && value != null) { if (typeof(value) == 'object' && value != null) {
if (ELEMENT_KEY in value) if (ELEMENT_KEY in value)
return this.retrieveItem_(value[ELEMENT_KEY]); return cache.retrieveItem(value[ELEMENT_KEY]);
var obj = (typeof(value.length) == 'number') ? [] : {}; var obj = (typeof(value.length) == 'number') ? [] : {};
for (var prop in value) for (var prop in value)
obj[prop] = this.unwrap(value[prop]); obj[prop] = unwrap(value[prop], cache);
return obj; return obj;
} }
return value; return value;
}
};
/**
* Returns the global object cache for the page.
* @return {!Cache} The page's object cache.
*/
function getPageCache() {
// We use the same key as selenium's javascript/atoms/inject.js.
var key = '$wdc_';
if (!(key in document))
document[key] = new Cache();
return document[key];
} }
/** /**
...@@ -168,11 +173,11 @@ function callFunction(func, args, opt_unwrappedReturn) { ...@@ -168,11 +173,11 @@ function callFunction(func, args, opt_unwrappedReturn) {
cache.clearStale(); cache.clearStale();
if (opt_unwrappedReturn) if (opt_unwrappedReturn)
return func.apply(null, cache.unwrap(args)); return func.apply(null, unwrap(args, cache));
var status = 0; var status = 0;
try { try {
var returnValue = cache.wrap(func.apply(null, cache.unwrap(args))); var returnValue = wrap(func.apply(null, unwrap(args, cache)));
} catch (error) { } catch (error) {
status = error.code || StatusCode.UNKNOWN_ERROR; status = error.code || StatusCode.UNKNOWN_ERROR;
var returnValue = error.message; var returnValue = error.message;
......
...@@ -4,13 +4,21 @@ ...@@ -4,13 +4,21 @@
<script src='call_function.js'></script> <script src='call_function.js'></script>
<script> <script>
function clearCache() {
getPageCache().cache_ = {};
}
function testCallFunctionNoArgs() { function testCallFunctionNoArgs() {
clearCache();
var result = callFunction(function() { return 1; }, []); var result = callFunction(function() { return 1; }, []);
assertEquals(0, result.status); assertEquals(0, result.status);
assertEquals(1, result.value); assertEquals(1, result.value);
} }
function testCallFunctionThrows() { function testCallFunctionThrows() {
clearCache();
var result = callFunction(function() { throw new Error('fake error'); }, []); var result = callFunction(function() { throw new Error('fake error'); }, []);
assertEquals(StatusCode.UNKNOWN_ERROR, result.status); assertEquals(StatusCode.UNKNOWN_ERROR, result.status);
assertEquals('fake error', result.value); assertEquals('fake error', result.value);
...@@ -26,120 +34,129 @@ function testCallFunctionThrows() { ...@@ -26,120 +34,129 @@ function testCallFunctionThrows() {
} }
function testCallFunctionArgs() { function testCallFunctionArgs() {
clearCache();
function func(primitive, elem) { function func(primitive, elem) {
return [primitive, elem.querySelector('div')]; return [primitive, elem.querySelector('div')];
} }
var cache = getPageCache(); var result = callFunction(func, [1, wrap(document)]);
var result = callFunction(func, [1, cache.wrap(document)]);
assertEquals(0, result.status); assertEquals(0, result.status);
assertEquals(1, result.value[0]); assertEquals(1, result.value[0]);
assertEquals(document.querySelector('div'), cache.unwrap(result.value[1])); var cache = getPageCache();
assertEquals(document.querySelector('div'), unwrap(result.value[1], cache));
} }
function testCallFunctionArgsUnwrappedReturn() { function testCallFunctionArgsUnwrappedReturn() {
clearCache();
function func(elem) { function func(elem) {
return elem.querySelector('div'); return elem.querySelector('div');
} }
var cache = getPageCache(); var result = callFunction(func, [wrap(document)], true);
var result = callFunction(func, [cache.wrap(document)], true);
assertEquals(document.querySelector('div'), result); assertEquals(document.querySelector('div'), result);
} }
function testCacheWrap() { function testCacheWrap() {
var cache = new Cache(); clearCache();
assertEquals(1, cache.wrap(1));
assertEquals(1, cache.unwrap(1)); assertEquals(1, wrap(1));
assertEquals("1", cache.wrap("1")); assertEquals(1, unwrap(1));
assertEquals("1", cache.unwrap("1")); assertEquals("1", wrap("1"));
assertEquals(false, cache.wrap(false)); assertEquals("1", unwrap("1"));
assertEquals(false, cache.unwrap(false)); assertEquals(false, wrap(false));
assertEquals(null, cache.wrap(null)); assertEquals(false, unwrap(false));
assertEquals(null, cache.unwrap(null)); assertEquals(null, wrap(null));
assertEquals(undefined, cache.wrap(undefined)); assertEquals(null, unwrap(null));
assertEquals(undefined, cache.unwrap(undefined)); assertEquals(undefined, wrap(undefined));
assertEquals(undefined, unwrap(undefined));
function func() {} function func() {}
assertEquals(func, cache.wrap(func)); assertEquals(func, wrap(func));
assertEquals(func, cache.unwrap(func)); assertEquals(func, unwrap(func));
var cache = getPageCache();
var arr = [1, new Array(1, new Object({a: 1, b: {a: 1, b: {}, c: 3}}), 3)]; var arr = [1, new Array(1, new Object({a: 1, b: {a: 1, b: {}, c: 3}}), 3)];
var originalJson = JSON.stringify(arr); var originalJson = JSON.stringify(arr);
arr[1][1].b.b[ELEMENT_KEY] = cache.nextId_.toString(); arr[1][1].b.b[ELEMENT_KEY] = cache.idPrefix_ + ':' + cache.nextId_;
var wrappedJson = JSON.stringify(arr); var wrappedJson = JSON.stringify(arr);
arr[1][1].b.b = document; arr[1][1].b.b = document;
assertEquals(wrappedJson, JSON.stringify(cache.wrap(arr))); assertEquals(wrappedJson, JSON.stringify(wrap(arr)));
var unwrapped = cache.unwrap(JSON.parse(wrappedJson)); var unwrapped = unwrap(JSON.parse(wrappedJson), cache);
assertEquals(document, unwrapped[1][1].b.b); assertEquals(document, unwrapped[1][1].b.b);
unwrapped[1][1].b.b = {}; unwrapped[1][1].b.b = {};
assertEquals(originalJson, JSON.stringify(unwrapped)); assertEquals(originalJson, JSON.stringify(unwrapped));
} }
function testCacheDoubleWrap() { function testCacheDoubleWrap() {
var cache = new Cache(); clearCache();
assertEquals(cache.wrap(document)[ELEMENT_KEY],
cache.wrap(document)[ELEMENT_KEY]); assertEquals(wrap(document)[ELEMENT_KEY], wrap(document)[ELEMENT_KEY]);
} }
function testCacheUnwrapThrows() { function testCacheUnwrapThrows() {
clearCache();
try { try {
var cache = new Cache();
var wrapped = {}; var wrapped = {};
wrapped[ELEMENT_KEY] = '1'; wrapped[ELEMENT_KEY] = '1';
cache.unwrap(wrapped); unwrap(wrapped, getPageCache());
assert(false);
} catch (e) { } catch (e) {
return;
} }
assert(false);
} }
function testClearStale() { function testClearStale() {
clearCache();
var doc = document; var doc = document;
var div = doc.querySelector('div'); var div = doc.querySelector('div');
var span = doc.querySelector('span'); var span = doc.querySelector('span');
var cache = new Cache(); var wrappedDoc = wrap(doc);
var wrappedDoc = cache.wrap(doc); var wrappedDiv = wrap(div);
var wrappedDiv = cache.wrap(div); var wrappedSpan = wrap(span);
var wrappedSpan = cache.wrap(span);
var cache = getPageCache();
cache.clearStale(); cache.clearStale();
assertEquals(doc, cache.unwrap(wrappedDoc)); assertEquals(doc, unwrap(wrappedDoc, cache));
assertEquals(div, cache.unwrap(wrappedDiv)); assertEquals(div, unwrap(wrappedDiv, cache));
assertEquals(span, cache.unwrap(wrappedSpan)); assertEquals(span, unwrap(wrappedSpan, cache));
div.removeChild(span); div.removeChild(span);
cache.clearStale(); cache.clearStale();
assertEquals(doc, cache.unwrap(wrappedDoc)); assertEquals(doc, unwrap(wrappedDoc, cache));
assertEquals(div, cache.unwrap(wrappedDiv)); assertEquals(div, unwrap(wrappedDiv, cache));
try { try {
cache.unwrap(wrappedSpan); unwrap(wrappedSpan, cache);
assert(false);
} catch (e) { } catch (e) {
return;
} }
assert(false);
} }
function testCacheQuerySelector() { function testCacheQuerySelector() {
var cache = new Cache(); clearCache();
var cache = getPageCache();
assertEquals(document.querySelector('div'), assertEquals(document.querySelector('div'),
cache.unwrap(cache.wrap(document.querySelector('div')))); unwrap(wrap(document.querySelector('div')), cache));
assertEquals(document.querySelectorAll('div')[0], assertEquals(document.querySelectorAll('div')[0],
cache.unwrap(cache.wrap(document.querySelectorAll('div')))[0]); unwrap(wrap(document.querySelectorAll('div')), cache)[0]);
} }
function testCacheStaleRef() { function testCacheStaleRef() {
var cache = new Cache(); clearCache();
var cache = getPageCache();
var img = document.createElement('img'); var img = document.createElement('img');
document.body.appendChild(img); document.body.appendChild(img);
var wrappedImg = cache.wrap(img); var wrappedImg = wrap(img);
document.body.removeChild(img); document.body.removeChild(img);
cache.clearStale(); cache.clearStale();
try { try {
cache.unwrap(wrappedImg); unwrap(wrappedImg, cache);
assert(false);
} catch (e) { } catch (e) {
assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code); assertEquals(StatusCode.STALE_ELEMENT_REFERENCE, e.code);
return;
} }
assert(false);
} }
</script> </script>
......
...@@ -36,9 +36,6 @@ _REVISION_NEGATIVE_FILTER['HEAD'] = [ ...@@ -36,9 +36,6 @@ _REVISION_NEGATIVE_FILTER['HEAD'] = [
'CorrectEventFiringTest.testShouldFireEventsInTheRightOrder', 'CorrectEventFiringTest.testShouldFireEventsInTheRightOrder',
'CorrectEventFiringTest.testShouldFireFocusEventWhenClicking', 'CorrectEventFiringTest.testShouldFireFocusEventWhenClicking',
'DragAndDropTest.testDragTooFar', 'DragAndDropTest.testDragTooFar',
'ElementEqualityTest.testAnElementFoundInADifferentFrameViaJsShouldHaveSameId',
'ElementFindingTest.testAnElementFoundInADifferentFrameIsStale',
'ElementFindingTest.testAnElementFoundInADifferentFrameViaJsCanBeUsed',
'ExecutingAsyncJavascriptTest.includesAlertTextInUnhandledAlertException', 'ExecutingAsyncJavascriptTest.includesAlertTextInUnhandledAlertException',
'ExecutingAsyncJavascriptTest.throwsIfAlertHappensDuringScript', 'ExecutingAsyncJavascriptTest.throwsIfAlertHappensDuringScript',
'ExecutingAsyncJavascriptTest.throwsIfAlertHappensDuringScriptWhichTimesOut', 'ExecutingAsyncJavascriptTest.throwsIfAlertHappensDuringScriptWhichTimesOut',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment