function fnChangeHandler1() {
				//retrieve contexts, every thing should be loaded
				var aContexts = oBinding.getContexts(0, 100);

				assert.equal(aContexts.length, 9, "All contexts on top level loaded");

				done();
			}
******************************************************************************************
	QUnit.test("Eventing - ODataModel V2 - DataRequested and DataReceived", function (assert) {
		var done = assert.async();

		setupAnalyticalBinding({}, function (oBinding, oModel) {
			var oRequestedSpy = sinon.spy(oBinding, 'fireDataRequested'),
				oReceivedSpy = sinon.spy(oBinding, 'fireDataReceived'),
				oRequestSentSpy = sinon.spy(oModel, 'fireRequestSent'),
				oRequestCompletedSpy = sinon.spy(oModel, 'fireRequestCompleted');

			oBinding.attachChange(fnChangeHandler1);
			oBinding.getContexts(0, 20, 100);

			function fnChangeHandler1() {
				assert.equal(oRequestedSpy.callCount, 1,
					"After Initial Loading: Number of dataRequested Events = 1");
				assert.equal(oReceivedSpy.callCount, 1,
					"After Initial Loading: Number of dataReceived Events = 1");

				assert.equal(oRequestSentSpy.callCount, 3,
					"After Initial Loading: Number of requestSent Events = 3");
				assert.equal(oRequestCompletedSpy.callCount, 3,
					"After Initial Loading: Number of requestCompleted Events = 3");

				oBinding.detachChange(fnChangeHandler1);

				oBinding.getContexts(0, 20, 100);

				oBinding.attachChange(fnExpandChangeHandler);
				oBinding.expand(0);
			}

			function fnExpandChangeHandler() {
				oBinding.detachChange(fnExpandChangeHandler);

				oBinding.attachChange(fnChangeHandler2);
				oBinding.getContexts(0, 20, 100);
			}

			function fnChangeHandler2() {
				oBinding.detachChange(fnChangeHandler2);

				assert.equal(oRequestedSpy.callCount, 2,
					"After Expand: Number of dataRequested Events = 2");
				assert.equal(oReceivedSpy.callCount, 2,
					"After Expand: Number of dataReceived Events = 2");

				assert.equal(oRequestSentSpy.callCount, 4,
					"After Expand: Number of requestSent Events = 4");
				assert.equal(oRequestCompletedSpy.callCount, 4,
					"After Expand: Number of requestCompleted Events = 4");

				done();
			}
		});
	});

	//*********************************************************************************************
	// BCP: 002075129500000644142021
[
	{analyticalInfoByProperty: {}, measure : "foo", result : false},
	{analyticalInfoByProperty: {foo : {}}, measure : "foo", result : false},
	{analyticalInfoByProperty: {foo : {total : true}}, measure : "foo", result : false},
	{analyticalInfoByProperty: {foo : {total : "truthy"}}, measure : "foo", result : false},
	{analyticalInfoByProperty: {foo : {total : false}}, measure : "foo", result : true},
	// not sure whether this may happen; keep it for compatibility
	{analyticalInfoByProperty: {foo : {total : ""}}, measure : "foo", result : true}
].forEach(function (oFixture, i) {
	QUnit.test("_isSkippingTotalForMeasure: #" + i, function (assert) {
		var oBinding = {
				mAnalyticalInfoByProperty : oFixture.analyticalInfoByProperty
			};

		// code under test
		assert.strictEqual(
			AnalyticalBinding.prototype._isSkippingTotalForMeasure.call(oBinding, oFixture.measure),
			oFixture.result);
	});
});

	//*********************************************************************************************
	// If a measure property has a sap:text annotation and in the analytical info only that text
	// property is contained and not the measure itself, the analytical binding has to request data
	// and must not fail. It should request the data as it would do if the measure property would be
	// requested with total=true. In this test a multi-unit case is contained, which leads to a
	// second $batch resolving the multi-unit case.
	// Tests _prepareGroupMembersQueryRequest, _createMultiUnitRepresentativeEntry and
	// _prepareReloadMeasurePropertiesQueryRequest.
	// BCP: 002075129500000644142021
	QUnit.test("Measure with sap:text annotation; multi unit case", function (assert) {
		var aAnalyticalInfo = [
				Object.assign({}, oGroupedColumn, {name : "SalesDocument"}),
				Object.assign({}, oVisibleColumn, {name : "CostOvrWithhold_F"}),
				Object.assign({}, oVisibleColumn, {name : "CostInGlobalCurrency_F"})
			],
			iCount = 0,
			done = assert.async(),
			that = this;

		setupAnalyticalBinding({}, function (oBinding, oModel) {
			oModel.attachBatchRequestCompleted(function () {
				iCount += 1;
				if (iCount === 1) {
					return; // wait for the second batch which resolves the multi-unit case
				}
				done();
			});
			that.oLogMock.expects("warning")
				.withExactArgs("Detected a multi-unit case, so sorting is only possible on leaves",
					"/CONTRACTPERFResults");

			oBinding.getContexts(0, 20, 0);
		}, aAnalyticalInfo, "/CONTRACTPERFResults");
	});

	//*********************************************************************************************
	// If a measure property has a sap:text annotation and in the analytical info only that text
	// property is contained and not the measure itself, the analytical binding has to request data
	// and must not fail. It should request the data as it would do if the measure property would be
	// requested with total=true. In this test auto expansion is done.
	// Tests _prepareGroupMembersAutoExpansionQueryRequest/prepareLevelMembersQueryRequest.
	// BCP: 002075129500000644142021
	QUnit.test("Measure with sap:text annotation; auto expand", function (assert) {
		var aAnalyticalInfo = [
				Object.assign({}, oGroupedColumn, {name : "SalesDocument"}),
				Object.assign({}, oGroupedColumn, {name : "SalesOrganization"}),
				Object.assign({}, oVisibleColumn, {name : "CostOvrWithhold_F"})
			],
			done = assert.async();

		setupAnalyticalBinding({noPaging: true, numberOfExpandedLevels: 2},
			function (oBinding, oModel) {
				oModel.attachBatchRequestCompleted(function () {
					done();
				});

				oBinding.getContexts(0, 20, 0);
			},
			aAnalyticalInfo, "/CONTRACTPERFResults");
	});

	//*********************************************************************************************
	QUnit.test("No $batch used, but percent encoding for spaces", function (assert) {
		var sBindingPath = "/ActualPlannedCosts(P_ControllingArea='US 1'"
				+ ",P_CostCenter='100-1000',P_CostCenterTo='999-9999')/Results",
			sExpectedPath = "/ActualPlannedCosts(P_ControllingArea='US%201'"
				+ ",P_CostCenter='100-1000',P_CostCenterTo='999-9999')/Results",
			done = assert.async();

		setupAnalyticalBinding({useBatchRequests: false}, function (oBinding, oModel) {
			sinon.stub(oModel, "read", function (sPath) {
				assert.strictEqual(sPath, sExpectedPath, "percent encoding of space done");

				oModel.read.restore();
				done();
			});

			oBinding.getContexts();
		}, undefined/*aAnalyticalInfo