From 12cc5fd0ccd7ae2981d07a59d5ccc6451b3d0d52 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 10 Jul 2020 16:54:22 +0000 Subject: [PATCH] [IMP] web: benchmark: revive benchmark suite The benchmark suite has been broken for a while, by several refactorings (e.g. use of native Promise). This commit makes it work again. We do not use it much, but maybe we should as it can be useful to track changes (mostly in view renderers) that impact performances. --- .../web/static/tests/views/form_benchmarks.js | 170 ++++++++------- .../static/tests/views/kanban_benchmarks.js | 157 +++++++------- .../web/static/tests/views/list_benchmarks.js | 204 +++++++++--------- addons/web/views/webclient_templates.xml | 41 +--- 4 files changed, 275 insertions(+), 297 deletions(-) diff --git a/addons/web/static/tests/views/form_benchmarks.js b/addons/web/static/tests/views/form_benchmarks.js index efd12741d66..b65e8a4ccce 100644 --- a/addons/web/static/tests/views/form_benchmarks.js +++ b/addons/web/static/tests/views/form_benchmarks.js @@ -1,94 +1,98 @@ odoo.define('web.form_benchmarks', function (require) { -"use strict"; + "use strict"; -var FormView = require('web.FormView'); -var testUtils = require('web.test_utils'); + const FormView = require('web.FormView'); + const testUtils = require('web.test_utils'); -var createView = testUtils.createView; + const { createView } = testUtils; -QUnit.module('Form View', { - beforeEach: function () { - this.data = { - foo: { - fields: { - many2many: { string: "bar", type: "many2many", relation: 'bar'}, + QUnit.module('Form View', { + beforeEach: function () { + this.data = { + foo: { + fields: { + foo: {string: "Foo", type: "char"}, + many2many: { string: "bar", type: "many2many", relation: 'bar'}, + }, + records: [ + { id: 1, foo: "bar", many2many: []}, + ], + onchanges: {} }, - records: [ - { id: 1, many2many: []}, - ], - onchanges: {} - }, - bar: { - fields: { - char: {string: "char", type: "char"}, - many2many: { string: "pokemon", type: "many2many", relation: 'pokemon'}, + bar: { + fields: { + char: {string: "char", type: "char"}, + many2many: { string: "pokemon", type: "many2many", relation: 'pokemon'}, + }, + records: [], + onchanges: {} }, - records: [], - onchanges: {} - }, - pokemon: { - fields: { - name: {string: "Name", type: "char"}, + pokemon: { + fields: { + name: {string: "Name", type: "char"}, + }, + records: [], + onchanges: {} }, - records: [], - onchanges: {} - }, - }; - this.arch = null; - this.run = function (assert, done, cb) { - var data = this.data; - var arch = this.arch; - new Benchmark.Suite({}) - .add('form', function () { - var list = createView({ - View: FormView, - model: 'foo', - data: data, - arch: arch, - res_id: 1, - }); - if (cb) { - cb(list); - } - list.destroy(); - }) - .on('cycle', function(event) { - assert.ok(true, String(event.target)); - }) - .on('complete', done) - .run({ 'async': true }); - }; - } -}, function () { - QUnit.test('x2many with 250 rows, 2 fields (with many2many_tags, and modifiers), onchanges, and edition', function (assert) { - var done = assert.async(); - assert.expect(1); - - this.data.foo.onchanges.many2many = function (obj) { - obj.many2many = [5].concat(obj.many2many); - }; - for (var i = 2; i < 500; i) { - this.data.bar.records.push({ - id: i, - char: "automated data", - }); - this.data.foo.records[0].many2many.push(i); + }; + this.arch = null; + this.run = function (assert, viewParams, cb) { + const data = this.data; + const arch = this.arch; + return new Promise(resolve => { + new Benchmark.Suite({}) + .add('form', { + defer: true, + fn: async (deferred) => { + const form = await createView(Object.assign({ + View: FormView, + model: 'foo', + data, + arch, + }, viewParams)); + if (cb) { + await cb(form); + } + form.destroy(); + deferred.resolve(); + }, + }) + .on('cycle', event => { + assert.ok(true, String(event.target)); + }) + .on('complete', resolve) + .run({ async: true }); + }); + }; } - this.arch = - '
' + - '' + - '' + - '' + - '' + - '' + - '' + - '
'; - this.run(assert, done, function (form) { - testUtils.form.clickEdit(form); - form.$('.o_data_cell:first').click(); - form.$('input:first').val("tralala").trigger('input'); + }, function () { + QUnit.test('x2many with 250 rows, 2 fields (with many2many_tags, and modifiers), onchanges, and edition', function (assert) { + assert.expect(1); + + this.data.foo.onchanges.many2many = function (obj) { + obj.many2many = [5].concat(obj.many2many); + }; + for (let i = 2; i < 500; i++) { + this.data.bar.records.push({ + id: i, + char: "automated data", + }); + this.data.foo.records[0].many2many.push(i); + } + this.arch = ` +
+ + + + + + +
`; + return this.run(assert, { res_id: 1 }, async form => { + await testUtils.form.clickEdit(form); + await testUtils.dom.click(form.$('.o_data_cell:first')); + await testUtils.fields.editInput(form.$('input:first'), "tralala"); + }); }); }); }); - -}); \ No newline at end of file diff --git a/addons/web/static/tests/views/kanban_benchmarks.js b/addons/web/static/tests/views/kanban_benchmarks.js index d0df270089f..020067cb45c 100644 --- a/addons/web/static/tests/views/kanban_benchmarks.js +++ b/addons/web/static/tests/views/kanban_benchmarks.js @@ -1,83 +1,92 @@ odoo.define('web.kanban_benchmarks', function (require) { -"use strict"; + "use strict"; -var KanbanView = require('web.KanbanView'); -var testUtils = require('web.test_utils'); + const KanbanView = require('web.KanbanView'); + const { createView } = require('web.test_utils'); -var createView = testUtils.createView; - -QUnit.module('Kanban View', { - beforeEach: function () { - this.data = { - foo: { - fields: { - foo: {string: "Foo", type: "char"}, - bar: {string: "Bar", type: "boolean"}, - int_field: {string: "int_field", type: "integer", sortable: true}, - qux: {string: "my float", type: "float"}, + QUnit.module('Kanban View', { + beforeEach: function () { + this.data = { + foo: { + fields: { + foo: {string: "Foo", type: "char"}, + bar: {string: "Bar", type: "boolean"}, + int_field: {string: "int_field", type: "integer", sortable: true}, + qux: {string: "my float", type: "float"}, + }, + records: [ + { id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4}, + {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13}, + ] }, - records: [ - { id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4}, - {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13}, - ] - }, - }; - this.arch = null; - this.run = function (assert, done) { - var data = this.data; - var arch = this.arch; - new Benchmark.Suite({}) - .add('kanban', function () { - var kanban = createView({ - View: KanbanView, - model: 'foo', - data: data, - arch: arch, - }); - kanban.destroy(); - }) - .on('cycle', function(event) { - assert.ok(true, String(event.target)); - }) - .on('complete', done) - .run({ 'async': true }); - }; - } -}, function () { - QUnit.test('simple kanban view with 2 records', function (assert) { - var done = assert.async(); - assert.expect(1); - - this.arch = '' + - '
' + - '' + - '' + - '
' + - '
'; - - this.run(assert, done); - }); - - QUnit.test('simple kanban view with 200 records', function (assert) { - var done = assert.async(); - assert.expect(1); - - for (var i = 2; i < 200; i++) { - this.data.foo.records.push({ - id: i, - foo: "automated data" + i, - }); + }; + this.arch = null; + this.run = function (assert) { + const data = this.data; + const arch = this.arch; + return new Promise(resolve => { + new Benchmark.Suite({}) + .add('kanban', { + defer: true, + fn: async (deferred) => { + const kanban = await createView({ + View: KanbanView, + model: 'foo', + data, + arch, + }); + kanban.destroy(); + deferred.resolve(); + }, + }) + .on('cycle', event => { + assert.ok(true, String(event.target)); + }) + .on('complete', resolve) + .run({ async: true }); + }); + }; } + }, function () { + QUnit.test('simple kanban view with 2 records', function (assert) { + assert.expect(1); - this.arch = '' + - '
' + - '' + - '' + - '
' + - '
'; + this.arch = ` + + + +
+ + +
+
+
+
`; + return this.run(assert); + }); - this.run(assert, done); + QUnit.test('simple kanban view with 200 records', function (assert) { + assert.expect(1); + + for (let i = 2; i < 200; i++) { + this.data.foo.records.push({ + id: i, + foo: `automated data ${i}`, + }); + } + + this.arch = ` + + + +
+ + +
+
+
+
`; + return this.run(assert); + }); }); - -}); }); diff --git a/addons/web/static/tests/views/list_benchmarks.js b/addons/web/static/tests/views/list_benchmarks.js index 4dadbcb47bd..92d70054945 100644 --- a/addons/web/static/tests/views/list_benchmarks.js +++ b/addons/web/static/tests/views/list_benchmarks.js @@ -1,113 +1,113 @@ odoo.define('web.list_benchmarks', function (require) { -"use strict"; + "use strict"; -var ListView = require('web.ListView'); -var testUtils = require('web.test_utils'); + const ListView = require('web.ListView'); + const { createView } = require('web.test_utils'); -var createView = testUtils.createView; - -QUnit.module('List View', { - beforeEach: function () { - this.data = { - foo: { - fields: { - foo: {string: "Foo", type: "char"}, - bar: {string: "Bar", type: "boolean"}, - int_field: {string: "int_field", type: "integer", sortable: true}, - qux: {string: "my float", type: "float"}, + QUnit.module('List View', { + beforeEach: function () { + this.data = { + foo: { + fields: { + foo: {string: "Foo", type: "char"}, + bar: {string: "Bar", type: "boolean"}, + int_field: {string: "int_field", type: "integer", sortable: true}, + qux: {string: "my float", type: "float"}, + }, + records: [ + {id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4}, + {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13}, + ] }, - records: [ - { id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4}, - {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13}, - ] - }, - }; - this.arch = null; - this.run = function (assert, done, cb) { - var data = this.data; - var arch = this.arch; - new Benchmark.Suite({}) - .add('list', function () { - var list = createView({ - View: ListView, - model: 'foo', - data: data, - arch: arch, - }); - if (cb) { - cb(list); - } - list.destroy(); - }) - .on('cycle', function(event) { - assert.ok(true, String(event.target)); - }) - .on('complete', done) - .run({ 'async': true }); - }; - } -}, function () { - QUnit.test('simple readonly list with 2 rows and 2 fields', function (assert) { - var done = assert.async(); - assert.expect(1); - - this.arch =''; - this.run(assert, done); - }); - - QUnit.test('simple readonly list with 200 rows and 2 fields', function (assert) { - var done = assert.async(); - assert.expect(1); - - for (var i = 2; i < 200; i++) { - this.data.foo.records.push({ - id: i, - foo: "automated data", - int_field: 10 * i, - }); + }; + this.arch = null; + this.run = function (assert, cb) { + const data = this.data; + const arch = this.arch; + return new Promise(resolve => { + new Benchmark.Suite({}) + .add('list', { + defer: true, + fn: async (deferred) => { + const list = await createView({ + View: ListView, + model: 'foo', + data, + arch, + }); + if (cb) { + cb(list); + } + list.destroy(); + deferred.resolve(); + }, + }) + .on('cycle', event => { + assert.ok(true, String(event.target)); + }) + .on('complete', resolve) + .run({ async: true }); + }); + }; } - this.arch =''; - this.run(assert, done); - }); + }, function () { + QUnit.test('simple readonly list with 2 rows and 2 fields', function (assert) { + assert.expect(1); - QUnit.test('simple readonly list with 200 rows and 2 fields (with widgets)', function (assert) { - var done = assert.async(); - assert.expect(1); + this.arch = ''; + return this.run(assert); + }); - for (var i = 2; i < 200; i++) { - this.data.foo.records.push({ - id: i, - foo: "automated data", - int_field: 10 * i, + QUnit.test('simple readonly list with 200 rows and 2 fields', function (assert) { + assert.expect(1); + + for (let i = 2; i < 200; i++) { + this.data.foo.records.push({ + id: i, + foo: "automated data", + int_field: 10 * i, + }); + } + this.arch = ''; + return this.run(assert); + }); + + QUnit.test('simple readonly list with 200 rows and 2 fields (with widgets)', function (assert) { + assert.expect(1); + + for (let i = 2; i < 200; i++) { + this.data.foo.records.push({ + id: i, + foo: "automated data", + int_field: 10 * i, + }); + } + this.arch = ''; + return this.run(assert); + }); + + QUnit.test('editable list with 200 rows 4 fields', function (assert) { + assert.expect(1); + + for (let i = 2; i < 200; i++) { + this.data.foo.records.push({ + id: i, + foo: "automated data", + int_field: 10 * i, + bar: i % 2 === 0, + }); + } + this.arch = ` + + + + + + `; + return this.run(assert, list => { + list.$('.o_list_button_add').click(); + list.$('.o_list_button_discard').click(); }); - } - this.arch = ''; - this.run(assert, done); - }); - - QUnit.test('editable list with 200 rows 4 fields', function (assert) { - var done = assert.async(); - assert.expect(1); - - for (var i = 2; i < 200; i++) { - this.data.foo.records.push({ - id: i, - foo: "automated data", - int_field: 10 * i, - bar: i % 2 === 0, - }); - } - this.arch = '' + - '' + - '' + - '' + - '' + - ''; - this.run(assert, done, function (list) { - list.$buttons.find('.o_list_button_add').click(); - list.$buttons.find('.o_list_button_discard').click(); }); }); - -}); }); diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml index 0323694b5c4..c0dc0097a38 100644 --- a/addons/web/views/webclient_templates.xml +++ b/addons/web/views/webclient_templates.xml @@ -660,8 +660,6 @@ - -