HRESULT ComTestStoreService::BeginChangeRole( 
    /* [in] */ FABRIC_REPLICA_ROLE newRole,
    /* [in] */ IFabricAsyncOperationCallback *callback,
    /* [retval][out] */ IFabricAsyncOperationContext **context)
{
    if (callback == NULL || context == NULL) { return E_POINTER; }

    WAIT_FOR_SIGNAL_RESET(ServiceBeginChangeRoleBlock)
    CheckForReportFaultsAndDelays(testStoreService_.GetPartition(), ApiFaultHelper::Service, L"BeginChangeRole");

    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"BeginChangeRole")) return E_FAIL;

    ComPointer<ComCompletedAsyncOperationContext> operation = make_com<ComCompletedAsyncOperationContext>();
    HRESULT hr = E_FAIL;
    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"EndChangeRole")) 
    {
        hr = operation->Initialize(E_FAIL, ApiFaultHelper::Get().GetAsyncCompleteDelayTime(), root_, callback);
    }
    else
    {
        ErrorCode error = testStoreService_.OnChangeRole(newRole);
        TestSession::FailTestIfNot(error.IsSuccess(), "testStoreService_.OnChangeRole failed with error {0}", error);

        hr = operation->Initialize(root_, callback);
    }

    TestSession::FailTestIf(FAILED(hr), "operation->Initialize should not fail");
    return ComAsyncOperationContext::StartAndDetach<ComCompletedAsyncOperationContext>(std::move(operation), context);
}
HRESULT STDMETHODCALLTYPE ComTestStoreService::BeginUpdateEpoch( 
    /* [in] */ FABRIC_EPOCH const * epoch,
    /* [in] */ FABRIC_SEQUENCE_NUMBER previousEpochLastSequenceNumber,
    /* [in] */ IFabricAsyncOperationCallback *callback,
    /* [retval][out] */ IFabricAsyncOperationContext **context)
{
    if (epoch == NULL || callback == NULL || context == NULL) { return E_POINTER; }
   
    WAIT_FOR_SIGNAL_RESET(StateProviderBeginUpdateEpochBlock) 
    CheckForReportFaultsAndDelays(testStoreService_.GetPartition(), ApiFaultHelper::Provider, L"BeginUpdateEpoch");

    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Provider, L"BeginUpdateEpoch")) return E_FAIL;

    HRESULT hr;
    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Provider, L"EndUpdateEpoch")) 
    {
        hr = E_FAIL;
    }
    else
    {
        hr = testStoreService_.UpdateEpoch(epoch, previousEpochLastSequenceNumber);
    }

    ComPointer<ComCompletedAsyncOperationContext> operation = make_com<ComCompletedAsyncOperationContext>();
    hr = operation->Initialize(hr, root_, callback);
    TestSession::FailTestIf(FAILED(hr), "operation->Initialize should not fail");
    return ComAsyncOperationContext::StartAndDetach<ComCompletedAsyncOperationContext>(std::move(operation), context);
}
HRESULT ComTestStoreService::BeginClose( 
    /* [in] */ IFabricAsyncOperationCallback *callback,
    /* [retval][out] */ IFabricAsyncOperationContext **context)
{
    if (context == NULL) { return E_POINTER; }

    CheckForReportFaultsAndDelays(testStoreService_.GetPartition(), ApiFaultHelper::Service, L"BeginClose");

    HRESULT beginResult = testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"BeginClose") ? E_FAIL : S_OK;
    HRESULT endResult = testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"EndClose") ? E_FAIL : S_OK;

    if(!isClosedCalled_)
    {
        isClosedCalled_ = true;
        ErrorCode error = testStoreService_.OnClose();
        TestSession::FailTestIfNot(error.IsSuccess(), "testStoreService_.OnClose failed with error {0}", error);
    }

    if(FAILED(beginResult)) return E_FAIL;

    ComPointer<ComCompletedAsyncOperationContext> operation = make_com<ComCompletedAsyncOperationContext>();
    HRESULT hr = operation->Initialize(endResult, root_, callback);
    TestSession::FailTestIf(FAILED(hr), "operation->Initialize should not fail");
    return ComAsyncOperationContext::StartAndDetach<ComCompletedAsyncOperationContext>(std::move(operation), context);
}
//The test does not recover from data loss
HRESULT ComTestStoreService::BeginOnDataLoss( 
    /* [in] */ IFabricAsyncOperationCallback *callback,
    /* [retval][out] */ IFabricAsyncOperationContext **context)
{
    if (context == NULL) { return E_POINTER; }

    CheckForReportFaultsAndDelays(testStoreService_.GetPartition(), ApiFaultHelper::Provider, L"BeginOnDataLoss");
 
    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Provider, L"BeginOnDataLoss")) return E_FAIL;

    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Provider, L"EndOnDataLoss")) 
    {
        ComPointer<ComCompletedAsyncOperationContext> operation = make_com<ComCompletedAsyncOperationContext>();
        HRESULT hr = operation->Initialize(E_FAIL, ApiFaultHelper::Get().GetAsyncCompleteDelayTime(), root_, callback);
        TestSession::FailTestIf(FAILED(hr), "operation->Initialize should not fail");
        return ComAsyncOperationContext::StartAndDetach<ComCompletedAsyncOperationContext>(std::move(operation), context);
    }
    else
    {
        return testStoreService_.BeginOnDataLoss(callback, context);
    }
}
HRESULT ComTestStoreService::BeginOpen( 
    /* [in] */ FABRIC_REPLICA_OPEN_MODE openMode,
    /* [in] */ IFabricStatefulServicePartition *statefulServicePartition,
    /* [in] */ IFabricAsyncOperationCallback *callback,
    /* [retval][out] */ IFabricAsyncOperationContext **context)
{
    UNREFERENCED_PARAMETER(openMode);

    if (statefulServicePartition == NULL || callback == NULL || context == NULL) { return E_POINTER; }

    TestSession::FailTestIfNot(openMode == FABRIC_REPLICA_OPEN_MODE::FABRIC_REPLICA_OPEN_MODE_NEW, "Wrong open mode is passed in for volatile service");

    ComPointer<IFabricStatefulServicePartition3> partition;
    // TODO: tempPartition below is used for replicator only, remove when everything is switched to IFabricStatefulServicePartition1 interface (RDBug 3114076)
    ComPointer<IFabricStatefulServicePartition> tempPartition;
    partition.SetAndAddRef((IFabricStatefulServicePartition3*)statefulServicePartition);
    tempPartition.SetAndAddRef(statefulServicePartition);

    CheckForReportFaultsAndDelays(tempPartition, ApiFaultHelper::Service, L"BeginOpen");


    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"BeginOpen")) 
    {
        return E_FAIL;
    }

    ComPointer<ComCompletedAsyncOperationContext> operation = make_com<ComCompletedAsyncOperationContext>();
    HRESULT hr = E_FAIL;
    bool streamFaultsAndRequireServiceAckEnabled = false;

    if (testStoreService_.ShouldFailOn(ApiFaultHelper::Service, L"EndOpen")) 
    {
        hr = operation->Initialize(E_FAIL, ApiFaultHelper::Get().GetAsyncCompleteDelayTime(), root_, callback);
    }
    else
    {
        Common::ScopedHeap heap;
        ComPointer<IFabricStateReplicator> stateReplicator;
        ComPointer<IFabricReplicator> replicationEngine;
        FABRIC_REPLICATOR_SETTINGS replicatorSettings = { 0 };
        FABRIC_REPLICATOR_SETTINGS_EX1 replicatorSettingsEx1 = { 0 };
        FABRIC_REPLICATOR_SETTINGS_EX2 replicatorSettingsEx2 = { 0 };
        FABRIC_REPLICATOR_SETTINGS_EX3 replicatorSettingsEx3 = { 0 };
        FABRIC_REPLICATOR_SETTINGS_EX4 replicatorSettingsEx4 = { 0 };

        replicatorSettings.Flags = FABRIC_REPLICATOR_SETTINGS_NONE; // no memory limit, default number of items limit = 1024.
        replicatorSettings.Reserved = &replicatorSettingsEx1;
        replicatorSettingsEx1.Reserved = &replicatorSettingsEx2;
        replicatorSettingsEx2.Reserved = &replicatorSettingsEx3;
        replicatorSettingsEx3.Reserved = &replicatorSettingsEx4;
        replicatorSettingsEx4.Reserved = NULL;

		ReplicatorSettingServiceInitDataParser rsParser(testStoreService_.InitDataString);
        auto inputReplicatorSettings = rsParser.CreateReplicatorSettings(testStoreService_.InitDataString, testStoreService_.GetPartitionId());
        inputReplicatorSettings->ToPublicApi(heap, replicatorSettings);

        HRESULT result = partition->CreateReplicator(this, &replicatorSettings, replicationEngine.InitializationAddress(), stateReplicator.InitializationAddress());
        TestSession::FailTestIfNot(result == S_OK, "GetReplicator did not return success");
        TestSession::FailTestIfNot((bool) stateReplicator, "stateReplicator is null");
        TestSession::FailTestIfNot((bool) replicationEngine, "replicationEngine is null");

        ComPointer<ComTestReplicator> testReplicator = make_com<ComTestReplicator>(replicationEngine, tempPartition, false, testStoreService_.ServiceName, testStoreService_.NodeId);
        result = testReplicator->QueryInterface(IID_IFabricReplicator, reinterpret_cast<void**>(replicationEngine_.InitializationAddress()));
        TestSession::FailTestIfNot(result == S_OK, "testReplicator->QueryInterface did not return success");

        ErrorCode error = testStoreService_.OnOpen(partition, stateReplicator, streamFaultsAndRequireServiceAckEnabled);
        TestSession::FailTestIfNot(error.IsSuccess(), "testStoreService_.OnOpen failed with error {0}", error);

        hr = operation->Initialize(root_, callback);
    }

    TestSession::FailTestIf(FAILED(hr), "operation->Initialize should not fail");
    return ComAsyncOperationContext::StartAndDetach<ComCompletedAsyncOperationContext>(std::move(operation), context);
}