goog.disposable.disposable_test.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of google-closure-library
Show all versions of google-closure-library
The Google Closure Library is a collection of JavaScript code
designed for use with the Google Closure JavaScript Compiler.
This non-official distribution was prepared by the ClojureScript
team at http://clojure.org/
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed 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.
goog.provide('goog.DisposableTest');
goog.setTestOnly('goog.DisposableTest');
goog.require('goog.Disposable');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.recordFunction');
var d1, d2;
// Sample subclass of goog.Disposable.
function DisposableTest() {
goog.Disposable.call(this);
this.element = document.getElementById('someElement');
}
goog.inherits(DisposableTest, goog.Disposable);
DisposableTest.prototype.disposeInternal = function() {
DisposableTest.superClass_.disposeInternal.call(this);
delete this.element;
};
// Class that doesn't inherit from goog.Disposable, but implements the
// disposable interface via duck typing.
function DisposableDuck() {
this.element = document.getElementById('someElement');
}
DisposableDuck.prototype.dispose = function() {
delete this.element;
};
// Class which calls dispose recursively.
function RecursiveDisposable() {
this.disposedCount = 0;
}
goog.inherits(RecursiveDisposable, goog.Disposable);
RecursiveDisposable.prototype.disposeInternal = function() {
++this.disposedCount;
assertEquals('Disposed too many times', 1, this.disposedCount);
this.dispose();
};
// Test methods.
function setUp() {
d1 = new goog.Disposable();
d2 = new DisposableTest();
}
function tearDown() {
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.OFF;
goog.Disposable.INCLUDE_STACK_ON_CREATION = true;
goog.Disposable.instances_ = {};
d1.dispose();
d2.dispose();
}
function testConstructor() {
assertFalse(d1.isDisposed());
assertFalse(d2.isDisposed());
assertEquals(document.getElementById('someElement'), d2.element);
}
function testDispose() {
assertFalse(d1.isDisposed());
d1.dispose();
assertTrue(
'goog.Disposable instance should have been disposed of', d1.isDisposed());
assertFalse(d2.isDisposed());
d2.dispose();
assertTrue(
'goog.DisposableTest instance should have been disposed of',
d2.isDisposed());
}
function testDisposeInternal() {
assertNotUndefined(d2.element);
d2.dispose();
assertUndefined(
'goog.DisposableTest.prototype.disposeInternal should ' +
'have deleted the element reference',
d2.element);
}
function testDisposeAgain() {
d2.dispose();
assertUndefined(
'goog.DisposableTest.prototype.disposeInternal should ' +
'have deleted the element reference',
d2.element);
// Manually reset the element to a non-null value, and call dispose().
// Because the object is already marked disposed, disposeInternal won't
// be called again.
d2.element = document.getElementById('someElement');
d2.dispose();
assertNotUndefined(
'disposeInternal should not be called again if the ' +
'object has already been marked disposed',
d2.element);
}
function testDisposeWorksRecursively() {
new RecursiveDisposable().dispose();
}
function testStaticDispose() {
assertFalse(d1.isDisposed());
goog.dispose(d1);
assertTrue(
'goog.Disposable instance should have been disposed of', d1.isDisposed());
assertFalse(d2.isDisposed());
goog.dispose(d2);
assertTrue(
'goog.DisposableTest instance should have been disposed of',
d2.isDisposed());
var duck = new DisposableDuck();
assertNotUndefined(duck.element);
goog.dispose(duck);
assertUndefined(
'goog.dispose should have disposed of object that ' +
'implements the disposable interface',
duck.element);
}
function testStaticDisposeOnNonDisposableType() {
// Call goog.dispose() with various types and make sure no errors are
// thrown.
goog.dispose(true);
goog.dispose(false);
goog.dispose(null);
goog.dispose(undefined);
goog.dispose('');
goog.dispose([]);
goog.dispose({});
function A() {}
goog.dispose(new A());
}
function testMonitoringFailure() {
function BadDisposable(){};
goog.inherits(BadDisposable, goog.Disposable);
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.PERMANENT;
var badDisposable = new BadDisposable;
assertArrayEquals(
'no disposable objects registered', [],
goog.Disposable.getUndisposedObjects());
assertThrows(
'the base ctor should have been called',
goog.bind(badDisposable.dispose, badDisposable));
}
function testGetUndisposedObjects() {
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.PERMANENT;
var d1 = new DisposableTest();
var d2 = new DisposableTest();
assertSameElements(
'the undisposed instances', [d1, d2],
goog.Disposable.getUndisposedObjects());
d1.dispose();
assertSameElements(
'1 undisposed instance left', [d2],
goog.Disposable.getUndisposedObjects());
d1.dispose();
assertSameElements(
'second disposal of the same object is no-op', [d2],
goog.Disposable.getUndisposedObjects());
d2.dispose();
assertSameElements(
'all objects have been disposed of', [],
goog.Disposable.getUndisposedObjects());
}
function testClearUndisposedObjects() {
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.PERMANENT;
var d1 = new DisposableTest();
var d2 = new DisposableTest();
d2.dispose();
goog.Disposable.clearUndisposedObjects();
assertSameElements(
'no undisposed object in the registry', [],
goog.Disposable.getUndisposedObjects());
assertThrows(
'disposal after clearUndisposedObjects()', function() { d1.dispose(); });
// d2 is already disposed of, the redisposal shouldn't throw error.
d2.dispose();
}
function testRegisterDisposable() {
var d1 = new DisposableTest();
var d2 = new DisposableTest();
d1.registerDisposable(d2);
d1.dispose();
assertTrue('d2 should be disposed when d1 is disposed', d2.isDisposed());
}
function testDisposeAll() {
var d1 = new DisposableTest();
var d2 = new DisposableTest();
goog.disposeAll(d1, d2);
assertTrue('d1 should be disposed', d1.isDisposed());
assertTrue('d2 should be disposed', d2.isDisposed());
}
function testDisposeAllRecursive() {
var d1 = new DisposableTest();
var d2 = new DisposableTest();
var d3 = new DisposableTest();
var d4 = new DisposableTest();
goog.disposeAll(d1, [[d2], d3, d4]);
assertTrue('d1 should be disposed', d1.isDisposed());
assertTrue('d2 should be disposed', d2.isDisposed());
assertTrue('d3 should be disposed', d3.isDisposed());
assertTrue('d4 should be disposed', d4.isDisposed());
}
function testCreationStack() {
if (!new Error().stack) return;
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.PERMANENT;
var disposableStack = new DisposableTest().creationStack;
// Check that the name of this test function occurs in the stack trace.
assertNotEquals(-1, disposableStack.indexOf('testCreationStack'));
}
function testMonitoredWithoutCreationStack() {
if (!new Error().stack) return;
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.PERMANENT;
goog.Disposable.INCLUDE_STACK_ON_CREATION = false;
var d1 = new DisposableTest();
// Check that it is tracked, but not with a creation stack.
assertUndefined(d1.creationStack);
assertSameElements(
'the undisposed instance', [d1], goog.Disposable.getUndisposedObjects());
}
function testOnDisposeCallback() {
var callback = goog.testing.recordFunction();
d1.addOnDisposeCallback(callback);
assertEquals('callback called too early', 0, callback.getCallCount());
d1.dispose();
assertEquals(
'callback should be called once on dispose', 1, callback.getCallCount());
}
function testOnDisposeCallbackOrder() {
var invocations = [];
var callback = function(str) { invocations.push(str); };
d1.addOnDisposeCallback(goog.partial(callback, 'a'));
d1.addOnDisposeCallback(goog.partial(callback, 'b'));
goog.dispose(d1);
assertArrayEquals(
'callbacks should be called in chronological order', ['a', 'b'],
invocations);
}
function testAddOnDisposeCallbackAfterDispose() {
var callback = goog.testing.recordFunction();
var scope = {};
goog.dispose(d1);
d1.addOnDisposeCallback(callback, scope);
assertEquals(
'Callback should be immediately called if already disposed', 1,
callback.getCallCount());
assertEquals(
'Callback scope should be respected', scope,
callback.getLastCall().getThis());
}
function testInteractiveMonitoring() {
var d1 = new DisposableTest();
goog.Disposable.MONITORING_MODE = goog.Disposable.MonitoringMode.INTERACTIVE;
var d2 = new DisposableTest();
assertSameElements(
'only 1 undisposed instance tracked', [d2],
goog.Disposable.getUndisposedObjects());
// No errors should be thrown.
d1.dispose();
assertSameElements(
'1 undisposed instance left', [d2],
goog.Disposable.getUndisposedObjects());
d2.dispose();
assertSameElements(
'all disposed', [], goog.Disposable.getUndisposedObjects());
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy