Объект Gmock неправильно передается в асинхронную функцию

Я пытаюсь издеваться над частями AWS SDK на С++ для тестирования. В частности, я издеваюсь над объектом KMSClient и DecryptOutcome. MockKMSClient настроен на передачу MockDecryptOutcome в DecryptResponseReceivedHandler.

Вот мои издевательские классы:

class MockDecryptOutcome : public Aws::KMS::Model::DecryptOutcome {
public:
    Aws::Utils::Base64::Base64 _Base64;

    MockDecryptOutcome(string request) {
        if (request == SUCCESS) {
            EXPECT_CALL(*this, IsSuccess()).WillRepeatedly(Return(true));
            Aws::KMS::Model::DecryptResult result;
            result.SetPlaintext(_Base64.Decode(SUCCESS));
            EXPECT_CALL(*this, GetResult()).WillRepeatedly(Return(result));
        } else {
            EXPECT_CALL(*this, IsSuccess()).WillRepeatedly(Return(false));
            if (request == GRANT_TOKEN_NEEDED) {
                EXPECT_CALL(*this, GetError()).WillRepeatedly(Return(Aws::KMS::KMSErrors::ACCESS_DENIED));
            } else if (request == ENDPOINT_ERROR) {
                EXPECT_CALL(*this, GetError()).WillRepeatedly(Return(Aws::KMS::KMSErrors::NETWORK_CONNECTION));
            }
        }
    }
    virtual ~MockDecryptOutcome() {};

    MOCK_METHOD0(IsSuccess, bool());
    MOCK_METHOD0(GetResult, Aws::KMS::Model::DecryptResult());
    MOCK_CONST_METHOD0(GetError, Aws::KMS::KMSErrors());
};

class MockKMSClient : public Aws::KMS::KMSClient {
public:
    MockKMSClient() {
        EXPECT_CALL(*this, DecryptAsync_impl(_, _)).WillRepeatedly(Invoke(this, &MockKMSClient::do_DecryptAsync));
    }

    virtual ~MockKMSClient() {};

    Aws::Utils::Base64::Base64 _Base64;

    // Have to invoke Mocked method manually to discard optional parameter
    void DecryptAsync(
        const Aws::KMS::Model::DecryptRequest& request,
        const Aws::KMS::DecryptResponseReceivedHandler& handler,
        const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context = nullptr
    ) const
    {
        DecryptAsync_impl(request, handler);
    }

    MOCK_CONST_METHOD2(
        DecryptAsync_impl,
        void(
            const Aws::KMS::Model::DecryptRequest& request,
            const Aws::KMS::DecryptResponseReceivedHandler& handler
        )
    );

    void do_DecryptAsync(
        const Aws::KMS::Model::DecryptRequest& request,
        const Aws::KMS::DecryptResponseReceivedHandler& handler
    )
    {
        const MockDecryptOutcome& outcome(_Base64.Encode(request.GetCiphertextBlob()));
        cout << &outcome << endl;
        handler(this, request, outcome, nullptr);
    }
};

Обработчик определен в AWS SDK здесь: http://sdk. amazonaws.com/cpp/api/LATEST/namespace_aws

class MockDecryptOutcome : public Aws::KMS::Model::DecryptOutcome {
public:
    Aws::Utils::Base64::Base64 _Base64;

    MockDecryptOutcome(string request) {
        if (request == SUCCESS) {
            EXPECT_CALL(*this, IsSuccess()).WillRepeatedly(Return(true));
            Aws::KMS::Model::DecryptResult result;
            result.SetPlaintext(_Base64.Decode(SUCCESS));
            EXPECT_CALL(*this, GetResult()).WillRepeatedly(Return(result));
        } else {
            EXPECT_CALL(*this, IsSuccess()).WillRepeatedly(Return(false));
            if (request == GRANT_TOKEN_NEEDED) {
                EXPECT_CALL(*this, GetError()).WillRepeatedly(Return(Aws::KMS::KMSErrors::ACCESS_DENIED));
            } else if (request == ENDPOINT_ERROR) {
                EXPECT_CALL(*this, GetError()).WillRepeatedly(Return(Aws::KMS::KMSErrors::NETWORK_CONNECTION));
            }
        }
    }
    virtual ~MockDecryptOutcome() {};

    MOCK_METHOD0(IsSuccess, bool());
    MOCK_METHOD0(GetResult, Aws::KMS::Model::DecryptResult());
    MOCK_CONST_METHOD0(GetError, Aws::KMS::KMSErrors());
};

class MockKMSClient : public Aws::KMS::KMSClient {
public:
    MockKMSClient() {
        EXPECT_CALL(*this, DecryptAsync_impl(_, _)).WillRepeatedly(Invoke(this, &MockKMSClient::do_DecryptAsync));
    }

    virtual ~MockKMSClient() {};

    Aws::Utils::Base64::Base64 _Base64;

    // Have to invoke Mocked method manually to discard optional parameter
    void DecryptAsync(
        const Aws::KMS::Model::DecryptRequest& request,
        const Aws::KMS::DecryptResponseReceivedHandler& handler,
        const std::shared_ptr<const Aws::Client::AsyncCallerContext>& context = nullptr
    ) const
    {
        DecryptAsync_impl(request, handler);
    }

    MOCK_CONST_METHOD2(
        DecryptAsync_impl,
        void(
            const Aws::KMS::Model::DecryptRequest& request,
            const Aws::KMS::DecryptResponseReceivedHandler& handler
        )
    );

    void do_DecryptAsync(
        const Aws::KMS::Model::DecryptRequest& request,
        const Aws::KMS::DecryptResponseReceivedHandler& handler
    )
    {
        const MockDecryptOutcome& outcome(_Base64.Encode(request.GetCiphertextBlob()));
        cout << &outcome << endl;
        handler(this, request, outcome, nullptr);
    }
};
1_k_m_s.html#a6bb4999b2fbc6cd499913779e42421b3

Вот функция обратного вызова:

    void KmsCallback::on_decrypt_callback(
        const Aws::KMS::KMSClient* client,
        const Aws::KMS::Model::DecryptRequest&,
        const Aws::KMS::Model::DecryptOutcome&                        outcome,
        const std::shared_ptr<const Aws::Client::AsyncCallerContext>&
    )
    {
        cout << &outcome << endl;
}

Наконец, здесь вызывается асинхронная функция:

kms_client->DecryptAsync(
                decrypt_request,
                std::bind(
                    &KmsCallback::on_decrypt_callback,
                    this,
                    std::placeholders::_1,
                    std::placeholders::_2,
                    std::placeholders::_3,
                    std::placeholders::_4
                )
            );

Запуск этого в тесте выводит два разных адреса памяти для переменных DecryptOutcome:

0x7f03b6064dc0
0x7f03b6064dc8

Я пытался использовать "новый" оператор, удаляя "const" и многие другие комбинации, чтобы заставить это работать без успеха. Мы ценим любые предложения.


person Oscar Courchaine    schedule 19.03.2018    source источник
comment
Где вызывается on_decrypt_callback() и с какими аргументами? Пожалуйста, предоставьте соответствующий тест. Кроме того, добавьте тег 'c++' или эту строку: <!-- language: lang-cpp --> перед кодом для его форматирования (подробнее см. здесь). Информация).   -  person Yksisarvinen    schedule 20.03.2018
comment
Спасибо за предложения; Я внес соответствующие изменения   -  person Oscar Courchaine    schedule 20.03.2018
comment
Я не уверен, что вы подразумеваете под работой, но я предполагаю, что вы хотите, чтобы адреса были идентичными? Если да, то посмотрите это: stackoverflow.com/questions/11593783/   -  person RA.    schedule 21.03.2018