Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8276)

Unified Diff: chrome/test/data/webui/settings/prefs_tests.js

Issue 1333473002: Support lists in <cr-settings-pref> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@PrefsTests
Patch Set: Now with 100% more correctness Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/test/data/webui/polymer_browser_test_base.js ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/data/webui/settings/prefs_tests.js
diff --git a/chrome/test/data/webui/settings/prefs_tests.js b/chrome/test/data/webui/settings/prefs_tests.js
index 95e8f487c94b30d9c6c726e009466fd1ee62cd3c..12c8deecfd3e16bbe6a7ee52978ee3321068a9f5 100644
--- a/chrome/test/data/webui/settings/prefs_tests.js
+++ b/chrome/test/data/webui/settings/prefs_tests.js
@@ -5,6 +5,15 @@
/** @fileoverview Suite of tests for cr-settings-prefs. */
cr.define('cr_settings_prefs', function() {
/**
+ * Creates a deep copy of the object.
+ * @param {!Object} obj
+ * @return {!Object}
+ */
+ function deepCopy(obj) {
+ return JSON.parse(JSON.stringify(obj));
+ }
+
+ /**
* Mock of chrome.settingsPrivate API.
* @constructor
* @extends {chrome.settingsPrivate}
@@ -12,6 +21,7 @@ cr.define('cr_settings_prefs', function() {
function MockSettingsApi() {
this.prefs = {};
this.listener_ = null;
+ this.rand_ = getPseudoRand();
// Hack alert: bind this instance's onPrefsChanged members to this.
this.onPrefsChanged = {
@@ -24,6 +34,8 @@ cr.define('cr_settings_prefs', function() {
this.addBooleanPref_('browser.enable_html5', true);
this.addNumberPref_('device.overclock', .6);
this.addStringPref_('homepage', 'example.com');
+ this.addListPref_('languages', generateList(10, String, this.rand_));
+ this.addListPref_('content.sites', generateList(2, Object, this.rand_));
}
MockSettingsApi.prototype = {
@@ -43,7 +55,7 @@ cr.define('cr_settings_prefs', function() {
// Send a copy of prefs to keep our internal state private.
var prefs = [];
for (var key in this.prefs)
- prefs.push(this.createCopy_(this.prefs[key]));
+ prefs.push(deepCopy(this.prefs[key]));
setTimeout(callback.bind(null, prefs));
},
@@ -59,32 +71,43 @@ cr.define('cr_settings_prefs', function() {
this.failNextSetPref_ = false;
return;
}
+ assertNotEquals(true, this.disallowSetPref_);
- // TODO(michaelpg): support list and dict prefs.
- var changed = this.prefs[key].value != value;
- this.prefs[key].value = value;
- setTimeout(function() {
- callback(true);
+ var changed = JSON.stringify(pref.value) != JSON.stringify(value);
+ pref.value = JSON.parse(JSON.stringify(value));
+ setTimeout(callback.bind(null,true));
+ if (changed) {
+ setTimeout(function() {
// Like chrome.settingsPrivate, send a notification when prefs change.
- if (changed)
- this.sendPrefChanges([key], [value]);
- }.bind(this));
+ this.sendPrefChanges([key], [deepCopy(value)]);
+ }.bind(this));
+ }
},
getPref: function(key, callback) {
var pref = this.prefs[key];
assertNotEquals(undefined, pref);
- setTimeout(callback.bind(null, this.createCopy_(pref)));
+ var copy = deepCopy(pref);
+ setTimeout(callback.bind(null, copy));
},
// Functions used by tests.
- /** Instructs the API to fail when setPref is next called. */
+ /** Instructs the API to return a failure when setPref is next called. */
failNextSetPref: function() {
this.failNextSetPref_ = true;
},
+ /** Instructs the API to assert (fail the test) if setPref is called. */
+ disallowSetPref: function() {
+ this.disallowSetPref_ = true;
+ },
+
+ allowSetPref: function() {
+ this.disallowSetPref_ = false;
+ },
+
/**
* Notifies the listener of pref changes.
* @param {!Array<string>} keys
@@ -97,11 +120,13 @@ cr.define('cr_settings_prefs', function() {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var pref = this.prefs[key];
+ assertNotEquals(undefined, pref);
pref.value = values[i];
- prefs.push(this.createCopy_(pref));
+ prefs.push(deepCopy(pref));
}
- setTimeout(this.listener_.bind(null, prefs));
+ this.listener_(prefs);
+// setTimeout(this.listener_.bind(null, prefs));
},
// Private methods for use by the mock API.
@@ -144,12 +169,11 @@ cr.define('cr_settings_prefs', function() {
},
/**
- * Creates a deep copy of the preference.
- * @param {chrome.settingsPrivate.PrefObject} pref
- * @return {chrome.settingsPrivate.PrefObject}
+ * @param {string} key
+ * @param {!Array} value
*/
- createCopy_: function(pref) {
- return JSON.parse(JSON.stringify(pref));
+ addListPref_: function(key, value) {
+ this.addPref_(chrome.settingsPrivate.PrefType.LIST, key, value);
},
};
@@ -170,6 +194,79 @@ cr.define('cr_settings_prefs', function() {
});
}
+ // Pseudo-random number generator using Fibonacci LFSR.
+ function getPseudoRand() {
+ // Start with any integer in [1, 65535].
+ var lfsr = 3465; // Chromium's melting point (F).
+ var bit;
+ return function() {
+ bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
+ lfsr = (lfsr >> 1) | (bit << 15);
+ return lfsr;
+ };
+ }
+
+ function generateList(length, valueType, rand) {
+ var list = [];
+ for (var i = 0; i < length; i++) {
+ if (valueType == Boolean) {
+ list.push(Boolean(rand() % 2));
+ } else if (valueType == Number) {
+ list.push(rand());
+ } else if (valueType == String) {
+ // Allow empty strings.
+ list.push(generateString(rand() % 20, rand));
+ } else if (valueType == Object) {
+ // Don't allow empty objects.
+ list.push(generateObject(rand() % 2 + 1, rand));
+ }
+ }
+
+ return list;
+ };
+
+ function generateString(length, rand) {
+ var s = '';
+ for (var i = 0; i < length; i++)
+ s += String.fromCharCode(65 + rand() % 26);
+ return s;
+ }
+
+ function generateObject(numProps, rand) {
+ var obj = {};
+ var types = [Boolean, Number, String, Array];
+ var typesIndex = 0;
+ for (var i = 0; i < numProps; i++) {
+ var prop;
+ do {
+ prop = generateString(rand() % 20 + 1, rand);
+ } while (obj[prop] != undefined);
+ switch(types[typesIndex++ % types.length]) {
+ case Boolean:
+ obj[prop] = Boolean(rand() % 2);
+ break;
+ case Number:
+ obj[prop] = rand();
+ break;
+ case String:
+ obj[prop] = generateString(rand() % 20, rand);
+ break;
+ case Array:
+ // Generate a list of booleans, numbers or strings.
+ obj[prop] = generateList(rand() % 10, types[rand() % 3], rand);
+ break;
+ }
+ }
+ return obj;
+ }
+/*
+ var pref = {
+ type: 'LIST',
+ key: key,
+ value: list
+ };
+ */
+
function registerTests() {
suite('CrSettingsPrefs', function() {
/**
@@ -229,7 +326,7 @@ cr.define('cr_settings_prefs', function() {
expectEquals(expectedPref.key, actualPref.key);
expectEquals(expectedPref.type, actualPref.type);
- if (expectedPref.type != chrome.settingsPrivate.LIST) {
+ if (expectedPref.type != chrome.settingsPrivate.PrefType.LIST) {
expectEquals(expectedPref.value, actualPref.value);
} else {
expectEquals(JSON.stringify(expectedPref.value),
@@ -238,7 +335,10 @@ cr.define('cr_settings_prefs', function() {
}
});
- test('forwards pref changes to API', function() {
+ test('forwards pref changes to API', function(done) {
+ var rand = getPseudoRand();
+ rand();rand();
+
// Test that cr-settings-prefs uses the setPref API.
prefs.set('prefs.browser.enable_flash.value', true);
expectTrue(mockApi.prefs['browser.enable_flash'].value);
@@ -246,17 +346,39 @@ cr.define('cr_settings_prefs', function() {
expectEquals(1.2, mockApi.prefs['device.overclock'].value);
prefs.set('prefs.homepage.value', 'chromium.org');
expectEquals('chromium.org', mockApi.prefs['homepage'].value);
-
- // Test that when setPref fails, the pref is reverted locally.
- mockApi.failNextSetPref();
- prefs.set('prefs.browser.enable_flash.value', false);
- mockApi.failNextSetPref();
- prefs.set('prefs.device.overclock.value', 2.0);
- mockApi.failNextSetPref();
- prefs.set('prefs.homepage.value', 'invalid-url');
+ var list = generateList(10, String, rand);
+ prefs.set('prefs.languages.value', deepCopy(list));
+ expectEquals(JSON.stringify(list),
+ JSON.stringify(mockApi.prefs['languages'].value));
+ var newList = deepCopy(mockApi.prefs['content.sites'].value);
+ var dict = newList[1];
+ var prop = Object.keys(dict)[0];
+ // Set a property (and append _ to ensure the value is different)
+ dict[prop] = generateString(10, rand) + '_';
+// var listOfDicts = generateList(3, Object, rand);
+ prefs.set('prefs.content.sites.value', deepCopy(newList));
+ expectEquals(JSON.stringify(newList),
+ JSON.stringify(mockApi.prefs['content.sites'].value));
+ PolymerTest.async(function() {
+ mockApi.disallowSetPref();
+ prefs.set('prefs.content.sites.value', deepCopy(newList));
+ mockApi.allowSetPref();
+
+ // Test that when setPref fails, the pref is reverted locally.
+ mockApi.failNextSetPref();
+ prefs.set('prefs.browser.enable_flash.value', false);
+ mockApi.failNextSetPref();
+ prefs.set('prefs.device.overclock.value', 2.0);
+ mockApi.failNextSetPref();
+ prefs.set('prefs.homepage.value', 'invalid-url');
+ mockApi.failNextSetPref();
+ prefs.set('prefs.languages.value', generateList(10, String, rand));
+ mockApi.failNextSetPref();
+ prefs.set('prefs.content.sites.value', generateList(3, Object, rand));
+ }).async(function() {
// Multiple asynchronous round trips need to happen.
- return Promise.all([
+ Promise.all([
waitUntilTrue(function() {
return prefs.prefs.browser.enable_flash.value;
}),
@@ -266,19 +388,101 @@ cr.define('cr_settings_prefs', function() {
waitUntilTrue(function() {
return prefs.prefs.homepage.value == 'chromium.org';
}),
- ]);
+ waitUntilTrue(function() {
+ return JSON.stringify(prefs.prefs.languages.value) ==
+ JSON.stringify(list);
+ }),
+ waitUntilTrue(function() {
+ return JSON.stringify(prefs.prefs.content.sites.value) ==
+ JSON.stringify(newList);
+ }),
+ ]).then(function() {
+ done();
+ });
+ });
});
test('responds to API changes', function(done) {
- mockApi.sendPrefChanges(['top_level_pref'], [false]);
- PolymerTest.async(function() {
- expectEquals(false, prefs.prefs.top_level_pref.value);
+ var rand = getPseudoRand();
- mockApi.sendPrefChanges(['top_level_pref'], [true]);
+ var topLevelPref = false;
+ var contentSites = generateList(2, Object, rand);
+ contentSites = [{E: 'e', F: 'ff'}, {G: true, H: false}];
+
+ mockApi.disallowSetPref();
+ PolymerTest.async(function() {
+ mockApi.sendPrefChanges(['top_level_pref', 'content.sites'],
+ [topLevelPref, deepCopy(contentSites)]);
}).async(function() {
- expectEquals(true, prefs.prefs.top_level_pref.value);
- done();
- });
+ expectEquals(topLevelPref, prefs.prefs.top_level_pref.value);
+ expectEquals(JSON.stringify(contentSites),
+ JSON.stringify(prefs.prefs.content.sites.value));
+
+ topLevelPref = true;
+ var oldContentSites = contentSites;
+ contentSites = deepCopy(contentSites);
+ var dict = contentSites[1];
+ var prop = Object.keys(contentSites[1])[0];
+ // Set a property (and append _ to ensure the value is different)
+ dict[prop] = generateString(10, rand) + '_';
+ mockApi.sendPrefChanges(['top_level_pref', 'content.sites'],
+ [topLevelPref, deepCopy(contentSites)]);
+ }).async(function() {
+ expectEquals(topLevelPref, prefs.prefs.top_level_pref.value);
+ expectEquals(JSON.stringify(contentSites),
+ JSON.stringify(prefs.prefs.content.sites.value));
+ }).async(function() {
+ // Shouldn't respond to non-changes.
+ mockApi.disallowSetPref();
+ mockApi.sendPrefChanges(['top_level_pref', 'content.sites'],
+ [topLevelPref, deepCopy(contentSites)]);
+ }).async(function() {}
+ ).async(done);
+ });
+ });
+
+ suite('pseudo-random number generator', function() {
+ test('generates pseudo-random numbers', function() {
+ var numbers = {};
+ var rand1 = getPseudoRand();
+ var rand2 = getPseudoRand();
+ for (var i = 0; i < 1000; i++) {
+ var num1 = rand1();
+ var num2 = rand2();
+ // Generators should have the same seed and algorithm.
+ expectEquals(num1, num2);
+ // Generator shouldn't cycle in the first few numbers.
+ expectEquals(undefined, numbers[num1]);
+ numbers[num1] = true;
+ }
+ });
+ });
+
+ suite('list generator', function() {
+ var rand;
+
+ function checkList(length, type) {
+ var list = generateList(length, type, rand);
+ expectEquals(length, list.length);
+ for (var i = 0; i < length; i++)
+ expectEquals(typeof list[i], type.name.toLowerCase());
+ return list;
+ }
+
+ setup(function() {
+ rand = getPseudoRand();
+ });
+
+ test('flat lists', function() {
+ checkList(10, Boolean);
+ checkList(20, Number);
+ checkList(5, String);
+ });
+
+ test('object lists', function() {
+ var list = checkList(40, Object);
+ for (var i = 0; i < 40; i++)
+ expectGT(Object.keys(list[i]).length, 0);
});
});
}
« no previous file with comments | « chrome/test/data/webui/polymer_browser_test_base.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698