withCache = (bSelected, fnProcessor) => {
			// "evil" change listener may call #isSelected/#setSelected...
			// Note: only critical if #withCache is sync!
			assert.strictEqual(oContext.bSelected, bSelected, "already up-to-date");
			assert.strictEqual(iKeepAliveChanged, bSelected ? 1 : 2, "housekeeping done");
			if (bDeleted || bIsHeaderContext) {
				assert.strictEqual(iSelectionChanged, 0, "not called");
			} else {
				assert.strictEqual(iSelectionChanged, bSelected ? 1 : 2, "housekeeping done");
			}

			if (bDestroyed) {
				setTimeout(() => {
					oContext.oBinding = undefined; // can only happen async
					fnProcessor({/*oCache*/}, "/some/path"); // no #setProperty
					fnDone();
				});
			} else {
				const oCache = {setProperty : mustBeMocked};
				this.mock(oCache).expects("setProperty")
					.withExactArgs("@$ui5.context.isSelected", bSelected, "/some/path");
				fnProcessor(oCache, "/some/path");
			}
		}
******************************************************************************************
[false, true].forEach((bDoNotUpdateAnnotation) => {
	[false, true].forEach((bDestroyed) => {
		[false, true].forEach((bDeleted) => {
			[false, true].forEach((bIsHeaderContext) => {
				const sTitle = "doSetSelected, update annotation = " + !bDoNotUpdateAnnotation
					+ ", context destroyed while waiting for cache = " + bDestroyed
					+ ", deleted context = " + bDeleted
					+ ", context is header context = " + bIsHeaderContext;
				if (bIsHeaderContext && (bDeleted || bDestroyed)) {
					return;
				}

	QUnit.test(sTitle, function (assert) {
		const fnDone = bDestroyed && !bDoNotUpdateAnnotation ? assert.async(2) : null;
		const oBinding = {
			getHeaderContext : mustBeMocked,
			onKeepAliveChanged : mustBeMocked
		};
		const oBindingMock = this.mock(oBinding);
		const oHeaderContext = {
			onSelectionChanged : mustBeMocked
		};
		const oHeaderContextMock = this.mock(oHeaderContext);
		const oContext = Context.create({/*oModel