function success(sPath, sPredicate) {
			assert.strictEqual(sPath.slice(_Helper.getPredicateIndex(sPath)), sPredicate);
		}
******************************************************************************************
[false, true].forEach(function (bNull) {
	var sTitle = "updateSelected: complex type was " + (bNull ? "null" : "missing") + " in cache";

	QUnit.test(sTitle, function (assert) {
		var oCacheValue = {},
			oHelperMock = this.mock(_Helper),
			oNewValue = {
				complex : {
					simple1 : "new1",
					simple2 : "new2",
					complex : null
				}
			},
			oNewValueJSON = JSON.stringify(oNewValue),
			aSelect = ["complex/simple1", "complex/simple2", "complex/complex/unseen"],
			aSelectJSON = JSON.stringify(aSelect);

		if (bNull) {
			oCacheValue.complex = null;
		}
		oHelperMock.expects("fireChange").withExactArgs("~mChangeListener~", "base/path/complex",
			sinon.match.same(oNewValue.complex));
		oHelperMock.expects("fireChange")
			.withExactArgs("~mChangeListener~", "base/path/complex/simple1", "new1");
		oHelperMock.expects("fireChange")
			.withExactArgs("~mChangeListener~", "base/path/complex/simple2", "new2");

		// code under test
		_Helper.updateSelected("~mChangeListener~", "base/path", oCacheValue, oNewValue, aSelect);

		assert.deepEqual(oCacheValue, oNewValue);
		assert.strictEqual(JSON.stringify(oNewValue), oNewValueJSON);
		assert.strictEqual(JSON.stringify(aSelect), aSelectJSON);
	});
});

	//*********************************************************************************************
	QUnit.test("updateSelected: complex type becomes null in cache", function (assert) {
		var oCacheValue = {
				toNull : {}
			},
			oHelperMock = this.mock(_Helper),
			oNewValue = {
				toNull : null
			},
			oNewValueJSON = JSON.stringify(oNewValue),
			aSelect = ["toNull/property"],
			aSelectJSON = JSON.stringify(aSelect);

		oHelperMock.expects("fireChanges")
			.withExactArgs("~mChangeListener~", "base/path/toNull",
				sinon.match.same(oCacheValue.toNull), true);

		// code under test
		_Helper.updateSelected("~mChangeListener~", "base/path", oCacheValue, oNewValue, aSelect);

		assert.deepEqual(oCacheValue, oNewValue);
		assert.strictEqual(JSON.stringify(oNewValue), oNewValueJSON);
		assert.strictEqual(JSON.stringify(aSelect), aSelectJSON);
	});

	//*********************************************************************************************
[undefined, ["selected"], ["selected/*"], ["foo", "bar", "*"]].forEach(function (aSelect) {
	var sTitle = "updateSelected: complex type is selected: " + aSelect;

	QUnit.test(sTitle, function (assert) {
		var oCacheValue = {
				selected : {
					changed : "old",
					nested : {
						changed : "old",
						unchanged : "same"
					},
					unchanged : "same"
				}
			},
			oHelperMock = this.mock(_Helper),
			oNewValue = {
				selected : {
					changed : "new1",
					nested : {
						changed : "new3",
						newComplex : {new : "new4"},
						newSimple : "new5",
						unchanged : "same"
					},
					new : "new2",
					unchanged : "same"
				}
			},
			oNewValueJSON = JSON.stringify(oNewValue),
			aSelectJSON = JSON.stringify(aSelect);

		function expectChange(sPath, vValue) {
			oHelperMock.expects("fireChange")
				.withExactArgs("~mChangeListener~", "base/path/" + sPath, vValue);
		}

		expectChange("selected", oNewValue.selected);
		expectChange("selected/changed", "new1");
		expectChange("selected/new", "new2");
		expectChange("selected/nested", oNewValue.selected.nested);
		expectChange("selected/nested/changed", "new3");
		expectChange("selected/nested/newComplex", oNewValue.selected.nested.newComplex);
		expectChange("selected/nested/newComplex/new", "new4");
		expectChange("selected/nested/newSimple", "new5");

		// code under test
		_Helper.updateSelected("~mChangeListener~", "base/path", oCacheValue, oNewValue, aSelect);

		assert.deepEqual(oCacheValue, oNewValue);
		assert.strictEqual(JSON.stringify(oNewValue), oNewValueJSON);
		assert.strictEqual(JSON.stringify(aSelect), aSelectJSON);
	});
});

	//*********************************************************************************************
	QUnit.test("updateAll: properties", function (assert) {
		var mChangeListeners = {},
			oHelperMock = this.mock(_Helper),
			oSource = {
				"@$ui5._" : {
					predicate : "('1')",
					ignore : true
				},
				changed : "new",
				fromNull : "new",
				unchanged : "same"
			},
			oTarget = {
				changed : "old",
				fromNull : null,
				unchanged : "same"
			},
			oUpdatedTarget = {
				"@$ui5._" : {predicate : "('1')"},
				changed : "new",
				fromNull : "new",
				unchanged : "same"
			};

		oHelperMock.expects("buildPath").withExactArgs("path", "@$ui5._");
		oHelperMock.expects("buildPath").withExactArgs("path", "changed").returns("~changed");
		oHelperMock.expects("buildPath").withExactArgs("path", "fromNull").returns("~fromNull");
		oHelperMock.expects("buildPath").withExactArgs("path", "unchanged");
		oHelperMock.expects("fireChange")
			.withExactArgs(sinon.match.same(mChangeListeners), "~changed", "new");
		oHelperMock.expects("fireChange")
			.withExactArgs(sinon.match.same(mChangeListeners), "~fromNull", "new");

		// code under test
		_Helper.updateAll(mChangeListeners, "path", oTarget, oSource);

		assert.deepEqual(oTarget, oUpdatedTarget);
	});

	//*********************************************************************************************
	QUnit.test("updateAll: recursion", function (assert) {
		var aAdded = [],
			mChangeListeners = {},
			oHelperMock = this.mock(_Helper),
			oSource = {
				updated : {},
				added : {}
			},
			oTarget = {
				updated : {}
			};

		oHelperMock.expects("updateAll") // obviously :-)
			.withExactArgs(sinon.match.same(mChangeListeners), "path", sinon.match.same(oTarget),
				sinon.match.same(oSource))
			.callThrough();
		oHelperMock.expects("buildPath").withExactArgs("path", "updated").returns("~updated");
		oHelperMock.expects("updateAll")
			.withExactArgs(sinon.match.same(mChangeListeners), "~updated",
				sinon.match.same(oTarget.updated), sinon.match.same(oSource.updated));
		oHelperMock.expects("buildPath").withExactArgs("path", "added").returns("~added");
		oHelperMock.expects("updateAll")
			.withExactArgs(sinon.match.same(mChangeListeners), "~added", {},
				sinon.match.same(oSource.added))
			.returns(aAdded);

		// code under test
		_Helper.updateAll(mChangeListeners, "path", oTarget, oSource);

		assert.strictEqual(oTarget.added, aAdded);
	});

	//*********************************************************************************************
	QUnit.test("updateAll: source property is null", function (assert) {
		var mChangeListeners = {},
			oHelperMock = this.mock(_Helper),
			oSource = {
				changed : null,
				unchanged : null,
				structure : null
			},
			oTarget = {
				changed : "old",
				unchanged : null,
				structure : {}
			};

		oHelperMock.expects("buildPath").withExactArgs("path", "changed").returns("~changed");
		oHelperMock.expects("buildPath").withExactArgs("path", "unchanged");
		oHelperMock.expects("buildPath").withExactArgs("path", "structure").returns("~structure");
		oHelperMock.expects("fireChange")
			.withExactArgs(sinon.match.same(mChangeListeners), "~changed", null);
		oHelperMock.expects("fireChanges")
			.withExactArgs(sinon.match.same(mChangeListeners), "~structure",
				sinon.match.same(oTarget.structure), true);

		// code under test
		_Helper.updateAll(mChangeListeners, "path", oTarget, oSource);

		assert.deepEqual(oTarget, oSource);
	});

	//*********************************************************************************************
	QUnit.test("updateAll: array", function (assert) {
		var oSource = {
				array : []
			},
			oTarget = {};

		this.mock(_Helper).expects("fireChange")
			.withExactArgs("~mChangeListeners~", "path/array", sinon.match.same(oSource.array),
				/*bForceUpdate