[gjs: 4/7] tests: Move some tests around
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 4/7] tests: Move some tests around
- Date: Sat, 17 Aug 2019 01:48:41 +0000 (UTC)
commit 25abb7c284369cbe624c0e750c640cf80442b3c3
Author: Philip Chimento <philip chimento gmail com>
Date: Tue Aug 6 17:38:01 2019 -0700
tests: Move some tests around
Test suites in testGIMarshalling, testEverythingBasic, or
testEverythingEncapsulated, that aren't part of the GIMarshallingTests
or Regress test suites from gobject-introspection, don't need to be in
those respective files.
The vfunc test is more appropriate for testGObjectClass and the GError
test is more appropriate for testExceptions.
The new file testIntrospection.js is a good place for the sort of
catch-all test that tests how certain aspects of introspection are
implemented in GJS.
GObject overrides, on the other hand, should be tested in a file
specific for them. We already have testGObjectClass,
testGObjectInterface, and testParamSpec where GObject overrides are
tested, but those are kind of separate topics and not necessarily the
right place for a general override such as GObject.set() to live. We
create a new testGObject.js file for overrides like that.
Makefile-test.am | 2 +
installed-tests/js/testEverythingBasic.js | 125 -----------------------
installed-tests/js/testEverythingEncapsulated.js | 18 +---
installed-tests/js/testExceptions.js | 26 +++++
installed-tests/js/testGIMarshalling.js | 71 -------------
installed-tests/js/testGObject.js | 50 +++++++++
installed-tests/js/testGObjectClass.js | 63 ++++++++++++
installed-tests/js/testIntrospection.js | 105 +++++++++++++++++++
8 files changed, 247 insertions(+), 213 deletions(-)
---
diff --git a/Makefile-test.am b/Makefile-test.am
index d2233ee4..ddef920d 100644
--- a/Makefile-test.am
+++ b/Makefile-test.am
@@ -207,11 +207,13 @@ common_jstests_files = \
installed-tests/js/testGettext.js \
installed-tests/js/testGIMarshalling.js \
installed-tests/js/testGLib.js \
+ installed-tests/js/testGObject.js \
installed-tests/js/testGObjectClass.js \
installed-tests/js/testGObjectInterface.js \
installed-tests/js/testGTypeClass.js \
installed-tests/js/testGio.js \
installed-tests/js/testImporter.js \
+ installed-tests/js/testIntrospection.js \
installed-tests/js/testLang.js \
installed-tests/js/testLegacyByteArray.js \
installed-tests/js/testLegacyClass.js \
diff --git a/installed-tests/js/testEverythingBasic.js b/installed-tests/js/testEverythingBasic.js
index bd42deab..ffd5bb16 100644
--- a/installed-tests/js/testEverythingBasic.js
+++ b/installed-tests/js/testEverythingBasic.js
@@ -2,13 +2,10 @@ const Regress = imports.gi.Regress;
const WarnLib = imports.gi.WarnLib;
// We use Gio to have some objects that we know exist
-imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
-const Gdk = imports.gi.Gdk;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
-const Gtk = imports.gi.Gtk;
describe('Life, the Universe and Everything', function () {
it('includes booleans', function () {
@@ -115,18 +112,6 @@ describe('Life, the Universe and Everything', function () {
runTest(bytes, 'MAX', 'test_int');
});
});
-
- it('warns when conversion is lossy', function () {
- GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
- '*cannot be safely stored*');
- GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
- '*cannot be safely stored*');
- void GLib.MAXINT64;
- void GLib.MAXUINT64;
- GLib.test_assert_expected_messages_internal('Gjs',
- 'testEverythingBasic.js', 0,
- 'Limits warns when conversion is lossy');
- });
});
describe('No implicit conversion to unsigned', function () {
@@ -137,11 +122,6 @@ describe('Life, the Universe and Everything', function () {
});
});
- it('throws when constructor called without new', function () {
- expect(() => Gio.AppLaunchContext())
- .toThrowError(/Constructor called as normal method/);
- });
-
describe('String arrays', function () {
it('marshalling in', function () {
expect(Regress.test_strv_in(['1', '2', '3'])).toBeTruthy();
@@ -405,60 +385,10 @@ describe('Life, the Universe and Everything', function () {
.toEqual('value2');
});
- it('enum has a $gtype property', function () {
- expect(Regress.TestEnumUnsigned.$gtype).toBeDefined();
- });
-
- it('enum $gtype property is enumerable', function () {
- expect('$gtype' in Regress.TestEnumUnsigned).toBeTruthy();
- });
-
- it('Number converts error to quark', function () {
- expect(Regress.TestError.quark()).toEqual(Number(Regress.TestError));
- });
-
it('converts enum to string', function () {
expect(Regress.TestEnum.param(Regress.TestEnum.VALUE4)).toEqual('value4');
});
- it('can be answered with GObject.set()', function () {
- let o = new Regress.TestObj();
- o.set({string: 'Answer', int: 42});
- expect(o.string).toBe('Answer');
- expect(o.int).toBe(42);
- });
-
- describe('Object properties on GtkBuilder-constructed objects', function () {
- let o1;
- beforeAll(function () {
- Gtk.init(null);
- });
-
- beforeEach(function () {
- const ui = `
- <interface>
- <object class="GtkButton" id="button">
- <property name="label">Click me</property>
- </object>
- </interface>`;
-
- let builder = Gtk.Builder.new_from_string(ui, -1);
- o1 = builder.get_object('button');
- });
-
- it('are found on the GObject itself', function () {
- expect(o1.label).toBe('Click me');
- });
-
- it('are found on the GObject\'s parents', function () {
- expect(o1.visible).toBeFalsy();
- });
-
- it('are found on the GObject\'s interfaces', function () {
- expect(o1.action_name).toBeNull();
- });
- });
-
describe('Object-valued GProperty', function () {
let o1, t1, t2;
beforeEach(function () {
@@ -578,30 +508,6 @@ describe('Life, the Universe and Everything', function () {
}).pend('Not yet implemented');
});
- describe('Signal alternative syntax', function () {
- let o, handler;
- beforeEach(function () {
- handler = jasmine.createSpy('handler');
- o = new Regress.TestObj();
- let handlerId = GObject.signal_connect(o, 'test', handler);
- handler.and.callFake(() =>
- GObject.signal_handler_disconnect(o, handlerId));
-
- GObject.signal_emit_by_name(o, 'test');
- });
-
- it('handler is called with the right object', function () {
- expect(handler).toHaveBeenCalledTimes(1);
- expect(handler).toHaveBeenCalledWith(o);
- });
-
- it('disconnected handler is not called', function () {
- handler.calls.reset();
- GObject.signal_emit_by_name(o, 'test');
- expect(handler).not.toHaveBeenCalled();
- });
- });
-
it('torture signature 0', function () {
let [y, z, q] = Regress.test_torture_signature_0(42, 'foo', 7);
expect(Math.floor(y)).toEqual(42);
@@ -679,32 +585,6 @@ describe('Life, the Universe and Everything', function () {
expect(Number(Gio.IOErrorEnum)).toEqual(Gio.io_error_quark());
});
- describe('thrown GError', function () {
- let err;
- beforeEach(function () {
- try {
- let file = Gio.file_new_for_path("\\/,.^!@&$_don't exist");
- file.read(null);
- } catch (x) {
- err = x;
- }
- });
-
- it('is an instance of error enum type', function () {
- expect(err instanceof Gio.IOErrorEnum).toBeTruthy();
- });
-
- it('matches error domain and code', function () {
- expect(err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND))
- .toBeTruthy();
- });
-
- it('has properties for domain and code', function () {
- expect(err.domain).toEqual(Gio.io_error_quark());
- expect(err.code).toEqual(Gio.IOErrorEnum.NOT_FOUND);
- });
- });
-
it('GError callback', function (done) {
Regress.test_gerror_callback(e => {
expect(e instanceof Gio.IOErrorEnum).toBeTruthy();
@@ -842,9 +722,4 @@ describe('Life, the Universe and Everything', function () {
.not.toThrow();
});
});
-
- it('presents GdkAtom as string', function () {
- expect(Gdk.Atom.intern('CLIPBOARD', false)).toBe('CLIPBOARD');
- expect(Gdk.Atom.intern('NONE', false)).toBe(null);
- });
});
diff --git a/installed-tests/js/testEverythingEncapsulated.js
b/installed-tests/js/testEverythingEncapsulated.js
index 45d13cf3..fd42cd8d 100644
--- a/installed-tests/js/testEverythingEncapsulated.js
+++ b/installed-tests/js/testEverythingEncapsulated.js
@@ -1,5 +1,4 @@
-const {GLib, GObject, Regress} = imports.gi;
-const System = imports.system;
+const {GObject, Regress} = imports.gi;
describe('Introspected structs', function () {
let struct;
@@ -289,21 +288,6 @@ describe('Introspected function length', function () {
});
});
-describe('Garbage collection of introspected objects', function () {
- // This tests a regression that would very rarely crash, but
- // when run under valgrind this code would show use-after-free.
- it('collects objects properly with signals connected', function (done) {
- function orphanObject() {
- let obj = new Regress.TestObj();
- obj.connect('notify', () => {});
- }
-
- orphanObject();
- System.gc();
- GLib.idle_add(GLib.PRIORITY_LOW, () => done());
- });
-});
-
describe('Introspected interface', function () {
const Implementor = GObject.registerClass({
Implements: [Regress.TestInterface],
diff --git a/installed-tests/js/testExceptions.js b/installed-tests/js/testExceptions.js
index 66514f8e..8e7b1e1d 100644
--- a/installed-tests/js/testExceptions.js
+++ b/installed-tests/js/testExceptions.js
@@ -165,3 +165,29 @@ describe('Exception from function with too few arguments', function () {
expect(() => file.read()).toThrowError(/Gio\.File\.read/);
});
});
+
+describe('thrown GError', function () {
+ let err;
+ beforeEach(function () {
+ try {
+ let file = Gio.file_new_for_path("\\/,.^!@&$_don't exist");
+ file.read(null);
+ } catch (x) {
+ err = x;
+ }
+ });
+
+ it('is an instance of error enum type', function () {
+ expect(err).toEqual(jasmine.any(Gio.IOErrorEnum));
+ });
+
+ it('matches error domain and code', function () {
+ expect(err.matches(Gio.io_error_quark(), Gio.IOErrorEnum.NOT_FOUND))
+ .toBeTruthy();
+ });
+
+ it('has properties for domain and code', function () {
+ expect(err.domain).toEqual(Gio.io_error_quark());
+ expect(err.code).toEqual(Gio.IOErrorEnum.NOT_FOUND);
+ });
+});
diff --git a/installed-tests/js/testGIMarshalling.js b/installed-tests/js/testGIMarshalling.js
index 50a76dee..915261a3 100644
--- a/installed-tests/js/testGIMarshalling.js
+++ b/installed-tests/js/testGIMarshalling.js
@@ -692,68 +692,6 @@ describe('Virtual function', function () {
});
});
-describe('GObject virtual function', function () {
- it('can have its property read', function () {
- expect(GObject.Object.prototype.vfunc_constructed).toBeTruthy();
- });
-
- it('can have its property overridden with an anonymous function', function () {
- let callback;
-
- let key = 'vfunc_constructed';
-
- class _SimpleTestClass1 extends GObject.Object {}
-
- if (GObject.Object.prototype.vfunc_constructed) {
- let parentFunc = GObject.Object.prototype.vfunc_constructed;
- _SimpleTestClass1.prototype[key] = function (...args) {
- parentFunc.call(this, ...args);
- callback('123');
- };
- } else {
- _SimpleTestClass1.prototype[key] = function () {
- callback('abc');
- };
- }
-
- callback = jasmine.createSpy('callback');
-
- const SimpleTestClass1 = GObject.registerClass({GTypeName: 'SimpleTestClass1'}, _SimpleTestClass1);
- new SimpleTestClass1();
-
- expect(callback).toHaveBeenCalledWith('123');
- });
-
- it('can access the parent prototype with super()', function () {
- let callback;
-
- class _SimpleTestClass2 extends GObject.Object {
- vfunc_constructed() {
- super.vfunc_constructed();
- callback('vfunc_constructed');
- }
- }
-
- callback = jasmine.createSpy('callback');
-
- const SimpleTestClass2 = GObject.registerClass({GTypeName: 'SimpleTestClass2'}, _SimpleTestClass2);
- new SimpleTestClass2();
-
- expect(callback).toHaveBeenCalledWith('vfunc_constructed');
- });
-
- it('handles non-existing properties', function () {
- const _SimpleTestClass3 = class extends GObject.Object {};
-
- _SimpleTestClass3.prototype.vfunc_doesnt_exist = function () {};
-
- if (GObject.Object.prototype.vfunc_doesnt_exist)
- fail('Virtual function should not exist');
-
- expect(() => GObject.registerClass({GTypeName: 'SimpleTestClass3'}, _SimpleTestClass3)).toThrow();
- });
-});
-
describe('Interface', function () {
it('can be returned', function () {
let ifaceImpl = new GIMarshallingTests.InterfaceImpl();
@@ -783,12 +721,3 @@ describe('GObject properties', function () {
expect(() => (obj.some_readonly = 35)).toThrow();
});
});
-
-describe('GDestroyNotify parameters', function () {
- it('throws when encountering a GDestroyNotify not associated with a callback', function () {
- // the 'destroy' argument applies to the data, which is not supported in
- // gobject-introspection
- expect(() => Gio.MemoryInputStream.new_from_data('foobar'))
- .toThrowError(/destroy/);
- });
-});
diff --git a/installed-tests/js/testGObject.js b/installed-tests/js/testGObject.js
new file mode 100644
index 00000000..bf56bb17
--- /dev/null
+++ b/installed-tests/js/testGObject.js
@@ -0,0 +1,50 @@
+// This is where overrides in modules/overrides/GObject.js are tested, except
+// for the class machinery, interface machinery, and GObject.ParamSpec, which
+// are big enough to get their own files.
+
+const {GLib, GObject} = imports.gi;
+
+describe('GObject overrides', function () {
+ const TestObj = GObject.registerClass({
+ Properties: {
+ int: GObject.ParamSpec.int('int', '', '', GObject.ParamFlags.READWRITE,
+ 0, GLib.MAXINT32, 0),
+ string: GObject.ParamSpec.string('string', '', '',
+ GObject.ParamFlags.READWRITE, ''),
+ },
+ Signals: {
+ test: {},
+ },
+ }, class TestObj extends GObject.Object {});
+
+ it('GObject.set()', function () {
+ const o = new TestObj();
+ o.set({string: 'Answer', int: 42});
+ expect(o.string).toBe('Answer');
+ expect(o.int).toBe(42);
+ });
+
+ describe('Signal alternative syntax', function () {
+ let o, handler;
+ beforeEach(function () {
+ handler = jasmine.createSpy('handler');
+ o = new TestObj();
+ const handlerId = GObject.signal_connect(o, 'test', handler);
+ handler.and.callFake(() =>
+ GObject.signal_handler_disconnect(o, handlerId));
+
+ GObject.signal_emit_by_name(o, 'test');
+ });
+
+ it('handler is called with the right object', function () {
+ expect(handler).toHaveBeenCalledTimes(1);
+ expect(handler).toHaveBeenCalledWith(o);
+ });
+
+ it('disconnected handler is not called', function () {
+ handler.calls.reset();
+ GObject.signal_emit_by_name(o, 'test');
+ expect(handler).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/installed-tests/js/testGObjectClass.js b/installed-tests/js/testGObjectClass.js
index dafdec1a..0a68c576 100644
--- a/installed-tests/js/testGObjectClass.js
+++ b/installed-tests/js/testGObjectClass.js
@@ -390,3 +390,66 @@ describe('GObject class with decorator', function () {
/\[object instance wrapper GType:Gjs_Derived jsobj@0x[a-f0-9]+ native@0x[a-f0-9]+\]/);
});
});
+
+describe('GObject virtual function', function () {
+ it('can have its property read', function () {
+ expect(GObject.Object.prototype.vfunc_constructed).toBeTruthy();
+ });
+
+ it('can have its property overridden with an anonymous function', function () {
+ let callback;
+
+ let key = 'vfunc_constructed';
+
+ class _SimpleTestClass1 extends GObject.Object {}
+
+ if (GObject.Object.prototype.vfunc_constructed) {
+ let parentFunc = GObject.Object.prototype.vfunc_constructed;
+ _SimpleTestClass1.prototype[key] = function (...args) {
+ parentFunc.call(this, ...args);
+ callback('123');
+ };
+ } else {
+ _SimpleTestClass1.prototype[key] = function () {
+ callback('abc');
+ };
+ }
+
+ callback = jasmine.createSpy('callback');
+
+ const SimpleTestClass1 = GObject.registerClass({GTypeName: 'SimpleTestClass1'}, _SimpleTestClass1);
+ new SimpleTestClass1();
+
+ expect(callback).toHaveBeenCalledWith('123');
+ });
+
+ it('can access the parent prototype with super()', function () {
+ let callback;
+
+ class _SimpleTestClass2 extends GObject.Object {
+ vfunc_constructed() {
+ super.vfunc_constructed();
+ callback('vfunc_constructed');
+ }
+ }
+
+ callback = jasmine.createSpy('callback');
+
+ const SimpleTestClass2 = GObject.registerClass({GTypeName: 'SimpleTestClass2'}, _SimpleTestClass2);
+ new SimpleTestClass2();
+
+ expect(callback).toHaveBeenCalledWith('vfunc_constructed');
+ });
+
+ it('handles non-existing properties', function () {
+ const _SimpleTestClass3 = class extends GObject.Object {};
+
+ _SimpleTestClass3.prototype.vfunc_doesnt_exist = function () {};
+
+ if (GObject.Object.prototype.vfunc_doesnt_exist)
+ fail('Virtual function should not exist');
+
+
+ expect(() => GObject.registerClass({GTypeName: 'SimpleTestClass3'}, _SimpleTestClass3)).toThrow();
+ });
+});
diff --git a/installed-tests/js/testIntrospection.js b/installed-tests/js/testIntrospection.js
new file mode 100644
index 00000000..814beb27
--- /dev/null
+++ b/installed-tests/js/testIntrospection.js
@@ -0,0 +1,105 @@
+// Various tests having to do with how introspection is implemented in GJS
+
+imports.gi.versions.Gdk = '3.0';
+imports.gi.versions.Gtk = '3.0';
+const {Gdk, Gio, GLib, GObject, Gtk} = imports.gi;
+const System = imports.system;
+
+describe('GLib.DestroyNotify parameter', function () {
+ it('throws when encountering a GDestroyNotify not associated with a callback', function () {
+ // the 'destroy' argument applies to the data, which is not supported in
+ // gobject-introspection
+ expect(() => Gio.MemoryInputStream.new_from_data('foobar'))
+ .toThrowError(/destroy/);
+ });
+});
+
+describe('Unsafe integer marshalling', function () {
+ it('warns when conversion is lossy', function () {
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*cannot be safely stored*');
+ GLib.test_expect_message('Gjs', GLib.LogLevelFlags.LEVEL_WARNING,
+ '*cannot be safely stored*');
+ void GLib.MAXINT64;
+ void GLib.MAXUINT64;
+ GLib.test_assert_expected_messages_internal('Gjs',
+ 'testEverythingBasic.js', 0,
+ 'Limits warns when conversion is lossy');
+ });
+});
+
+describe('Constructor', function () {
+ it('throws when constructor called without new', function () {
+ expect(() => Gio.AppLaunchContext())
+ .toThrowError(/Constructor called as normal method/);
+ });
+});
+
+describe('Enum classes', function () {
+ it('enum has a $gtype property', function () {
+ expect(Gio.BusType.$gtype).toBeDefined();
+ });
+
+ it('enum $gtype property is enumerable', function () {
+ expect('$gtype' in Gio.BusType).toBeTruthy();
+ });
+});
+
+describe('GError domains', function () {
+ it('Number converts error to quark', function () {
+ expect(Gio.ResolverError.quark()).toEqual(Number(Gio.ResolverError));
+ });
+});
+
+describe('Object properties on GtkBuilder-constructed objects', function () {
+ let o1;
+ beforeAll(function () {
+ Gtk.init(null);
+ });
+
+ beforeEach(function () {
+ const ui = `
+ <interface>
+ <object class="GtkButton" id="button">
+ <property name="label">Click me</property>
+ </object>
+ </interface>`;
+
+ let builder = Gtk.Builder.new_from_string(ui, -1);
+ o1 = builder.get_object('button');
+ });
+
+ it('are found on the GObject itself', function () {
+ expect(o1.label).toBe('Click me');
+ });
+
+ it('are found on the GObject\'s parents', function () {
+ expect(o1.visible).toBeFalsy();
+ });
+
+ it('are found on the GObject\'s interfaces', function () {
+ expect(o1.action_name).toBeNull();
+ });
+});
+
+describe('Garbage collection of introspected objects', function () {
+ // This tests a regression that would very rarely crash, but
+ // when run under valgrind this code would show use-after-free.
+ it('collects objects properly with signals connected', function (done) {
+ function orphanObject() {
+ let obj = new GObject.Object();
+ obj.connect('notify', () => {});
+ }
+
+ orphanObject();
+ System.gc();
+ GLib.idle_add(GLib.PRIORITY_LOW, () => done());
+ });
+});
+
+describe('Gdk.Atom', function () {
+ it('is presented as string', function () {
+ expect(Gdk.Atom.intern('CLIPBOARD', false)).toBe('CLIPBOARD');
+ expect(Gdk.Atom.intern('NONE', false)).toBe(null);
+ });
+});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]